Scott Meyers - Effective Modern C++

Здесь есть возможность читать онлайн «Scott Meyers - Effective Modern C++» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Город: Sebastopol, Год выпуска: 2014, ISBN: 2014, Издательство: O’Reilly, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Effective Modern C++: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Effective Modern C++»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Coming to grips with C++11 and C++14 is more than a matter of familiarizing yourself with the features they introduce (e.g., auto type declarations, move semantics, lambda expressions, and concurrency support). The challenge is learning to use those features
— so that your software is correct, efficient, maintainable, and portable. That's where this practical book comes in. It describes how to write truly great software using C++11 and C++14 — i.e., using
C++.
Topics include:
■ The pros and cons of braced initialization,
specifications, perfect forwarding, and smart pointer make functions
■ The relationships among
,
, rvalue references, and universal references
■ Techniques for writing clear, correct,
lambda expressions
■ How
differs from
, how each should be used, and how they relate to C++'s concurrency API
■ How best practices in “old” C++ programming (i.e., C++98) require revision for software development in modern C++
Effective Modern C++ For more than 20 years,
'
books (
,
, and
) have set the bar for C++ programming guidance. His clear, engaging explanations of complex technical material have earned him a worldwide following, keeping him in demand as a trainer, consultant, and conference presenter. He has a Ph.D. in Computer Science from Brown University.
“After I learned the C++ basics, I then learned how to use C++ in production code from Meyers' series of Effective C++ books. Effective Modern C++ is the most important how-to book for advice on key guidelines, styles, and idioms to use modern C++ effectively and well. Don't own it yet? Buy this one. Now.”
Herb Sutter
Chair of ISO C++ Standards Committee and C++ Software Architect at Microsoft

Effective Modern C++ — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Effective Modern C++», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

• Using std::promises and futures dodges these issues, but the approach uses heap memory for shared states, and it's limited to one-shot communication.

Item 40: Use std::atomicfor concurrency, volatilefor special memory.

Poor volatile. So misunderstood. It shouldn't even be in this chapter, because it has nothing to do with concurrent programming. But in other programming languages (e.g., Java and C#), it is useful for such programming, and even in C++, some compilers have imbued volatilewith semantics that render it applicable to concurrent software (but only when compiled with those compilers). It's thus worthwhile to discuss volatilein a chapter on concurrency if for no other reason than to dispel the confusion surrounding it.

The C++ feature that programmers sometimes confuse volatilewith —the feature that definitely does belong in this chapter — is the std::atomictemplate. Instantiations of this template (e.g., std::atomic, std::atomic, std::atomic, etc.) offer operations that are guaranteed to be seen as atomic by other threads. Once a std::atomicobject has been constructed, operations on it behave as if they were inside a mutex-protected critical section, but the operations are generally implemented using special machine instructions that are more efficient than would be the case if a mutex were employed.

Consider this code using std::atomic:

std::atomicai(0); // initialize ai to 0

ai = 10; // atomically set ai to 10

std::cout << ai; // atomically read ai's value

++ai; // atomically increment ai to 11

--ai; // atomically decrement ai to 10

During execution of these statements, other threads reading aimay see only values of 0, 10, or 11. No other values are possible (assuming, of course, that this is the only thread modifying ai).

Two aspects of this example are worth noting. First, in the “ std::cout << ai;” statement, the fact that aiis a std::atomicguarantees only that the read of aiis atomic. There is no guarantee that the entire statement proceeds atomically. Between the time ai's value is read and operator<<is invoked to write it to the standard output, another thread may have modified ai's value. That has no effect on the behavior of the statement, because operator<<for ints uses a by-value parameter for the intto output (the outputted value will therefore be the one that was read from ai), but it's important to understand that what's atomic in that statement is nothing more than the read of ai.

The second noteworthy aspect of the example is the behavior of the last two statements — the increment and decrement of ai. These are each read-modify-write (RMW) operations, yet they execute atomically. This is one of the nicest characteristics of the std::atomictypes: once a std::atomicobject has been constructed, all member functions on it, including those comprising RMW operations, are guaranteed to be seen by other threads as atomic.

In contrast, the corresponding code using volatileguarantees virtually nothing in a multithreaded context:

volatileint vi(0); // initialize vi to 0

vi = 10; // set vi to 10

std::cout << vi; // read vi's value

++vi; // increment vi to 11

--vi; // decrement vi to 10

During execution of this code, if other threads are reading the value of vi, they may see anything, e.g, -12, 68, 4090727 — anything! Such code would have undefined behavior, because these statements modify vi, so if other threads are reading viat the same time, there are simultaneous readers and writers of memory that's neither std::atomicnor protected by a mutex, and that's the definition of a data race.

As a concrete example of how the behavior of std::atomics and volatiles can differ in a multithreaded program, consider a simple counter of each type that's incremented by multiple threads. We'll initialize each to 0:

std::atomic ac(0); // "atomic counter"

volatile int vc(0); // "volatile counter"

We'll then increment each counter one time in two simultaneously running threads:

/*----- Thread 1 ----- */ /*------- Thread 2 ------- */

++ac; ++ac;

++vc; ++vc;

When both threads have finished, ac's value (i.e., the value of the std::atomic) must be 2, because each increment occurs as an indivisible operation. vc's value, on the other hand, need not be 2, because its increments may not occur atomically. Each increment consists of reading vc's value, incrementing the value that was read, and writing the result back into vc. But these three operations are not guaranteed to proceed atomically for volatileobjects, so it's possible that the component parts of the two increments of vcare interleaved as follows:

1. Thread 1 reads vc's value, which is 0.

2. Thread 2 reads vc's value, which is still 0.

3. Thread 1 increments the 0 it read to 1, then writes that value into vc.

4. Thread 2 increments the 0 it read to 1, then writes that value into vc.

vc's final value is therefore 1, even though it was incremented twice.

This is not the only possible outcome. vc's final value is, in general, not predictable, because vcis involved in a data race, and the Standard's decree that data races cause undefined behavior means that compilers may generate code to do literally anything. Compilers don't use this leeway to be malicious, of course. Rather, they perform optimizations that would be valid in programs without data races, and these optimizations yield unexpected and unpredictable behavior in programs where races are present.

The use of RMW operations isn't the only situation where std::atomics comprise a concurrency success story and volatiles suffer failure. Suppose one task computes an important value needed by a second task. When the first task has computed the value, it must communicate this to the second task. Item 39explains that one way for the first task to communicate the availability of the desired value to the second task is by using a std::atomic. Code in the task computing the value would look something like this:

std::atomicvalAvailable(false);

auto imptValue = computeImportantValue(); // compute value

valAvailable = true; // tell other task

// it's available

As humans reading this code, we know it's crucial that the assignment to imptValuetake place before the assignment to valAvailable, but all compilers see is a pair of assignments to independent variables. As a general rule, compilers are permitted to reorder such unrelated assignments. That is, given this sequence of assignments (where a, b, x, and ycorrespond to independent variables),

a = b;

x = y;

compilers may generally reorder them as follows:

x = y;

a = b;

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Effective Modern C++»

Представляем Вашему вниманию похожие книги на «Effective Modern C++» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Effective Modern C++»

Обсуждение, отзывы о книге «Effective Modern C++» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x