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++», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

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

Интервал:

Закладка:

Сделать

y = x; // conceptually read x again (see below)

x = 10; // write x

x = 20; // write x again

and optimize it to this:

auto y = x; // conceptually read x (see below)

x = 20; // write x

For special memory, this is clearly unacceptable behavior.

Now, as it happens, neither of these two statements will compile when xis std::atomic:

auto y = x; // error!

y = x; // error!

That's because the copy operations for std::atomicare deleted (see Item 11). And with good reason. Consider what would happen if the initialization of ywith xcompiled. Because xis std::atomic, y's type would be deduced to be std::atomic, too (see Item 2). I remarked earlier that one of the best things about std::atomics is that all their operations are atomic, but in order for the copy construction of yfrom xto be atomic, compilers would have to generate code to read xand write yin a single atomic operation. Hardware generally can't do that, so copy construction isn't supported for std::atomictypes. Copy assignment is deleted for the same reason, which is why the assignment from xto ywon't compile. (The move operations aren't explicitly declared in std::atomic, so, per the rules for compiler-generated special functions described in Item 17, std:: atomicoffers neither move construction nor move assignment.)

It's possible to get the value of xinto y, but it requires use of std::atomic's member functions loadand store. The loadmember function reads a std::atomic's value atomically, while the storemember function writes it atomically. To initialize ywith x, followed by putting x's value in y, the code must be written like this:

std::atomic y( x.load()); // read x

y.store(x.load()); // read x again

This compiles, but the fact that reading x(via x.load()) is a separate function call from initializing or storing to ymakes clear that there is no reason to expect either statement as a whole to execute as a single atomic operation.

Given that code, compilers could “optimize” it by storing x's value in a register instead of reading it twice:

register = x.load(); // read x into register

std::atomic y( register ); // init y with register value

y.store( register ); // store register value into y

The result, as you can see, reads from xonly once, and that's the kind of optimization that must be avoided when dealing with special memory. (The optimization isn't permitted for volatilevariables.)

The situation should thus be clear:

std::atomicis useful for concurrent programming, but not for accessing special memory.

volatileis useful for accessing special memory, but not for concurrent programming.

Because std::atomicand volatileserve different purposes, they can even be used together:

volatile std::atomicvai; // operations on vai are

// atomic and can't be

// optimized away

This could be useful if vaicorresponded to a memory-mapped I/O location that was concurrently accessed by multiple threads.

As a final note, some developers prefer to use std::atomic's loadand storemember functions even when they're not required, because it makes explicit in the source code that the variables involved aren't “normal.” Emphasizing that fact isn't unreasonable. Accessing a std::atomicis typically much slower than accessing a non- std::atomic, and we've already seen that the use of std::atomics prevents compilers from performing certain kinds of code reorderings that would otherwise be permitted. Calling out loads and stores of std::atomics can therefore help identify potential scalability chokepoints. From a correctness perspective, not seeing a call to storeon a variable meant to communicate information to other threads (e.g., a flag indicating the availability of data) could mean that the variable wasn't declared std::atomicwhen it should have been.

This is largely a style issue, however, and as such is quite different from the choice between std::atomicand volatile.

Things to Remember

std::atomicis for data accessed from multiple threads without using mutexes. It's a tool for writing concurrent software.

volatileis for memory where reads and writes should not be optimized away. It's a tool for working with special memory.

Chapter 8

Tweaks

For every general technique or feature in C++, there are circumstances where it's reasonable to use it, and there are circumstances where it's not. Describing when it makes sense to use a general technique or feature is usually fairly straightforward, but this chapter covers two exceptions. The general technique is pass by value, and the general feature is emplacement. The decision about when to employ them is affected by so many factors, the best advice I can offer is to consider their use. Nevertheless, both are important players in effective modern C++ programming, and the Items that follow provide the information you'll need to determine whether using them is appropriate for your software.

Item 41: Consider pass by value for copyable parameters that are cheap to move and always copied.

Some function parameters are intended to be copied. [22] In this Item, to “copy” a parameter generally means to use it as the source of a copy or move operation. Recall on page 2 that C++ has no terminology to distinguish a copy made by a copy operation from one made by a move operation. For example, a member function addNamemight copy its parameter into a private container. For efficiency, such a function should copy lvalue arguments, but move rvalue arguments:

class Widget {

public:

void addName( const std::string&newName) // take lvalue;

{ names.push_back(newName); } // copy it

void addName( std::string&&newName) // take rvalue;

{ names.push_back(std::move(newName)); } // move it; see

… // Item 25 for use

// of std::move

private:

std::vector names;

};

This works, but it requires writing two functions that do essentially the same thing. That chafes a bit: two functions to declare, two functions to implement, two functions to document, two functions to maintain. Ugh.

Furthermore, there will be two functions in the object code — something you might care about if you're concerned about your program's footprint. In this case, both functions will probably be inlined, and that's likely to eliminate any bloat issues related to the existence of two functions, but if these functions aren't inlined everywhere, you really will get two functions in your object code.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x