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

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

Интервал:

Закладка:

Сделать

template

void emplace_back( Args&&... args);

};

Here, the type parameter Argsis independent of vector's type parameter T, so Argsmust be deduced each time emplace_backis called. (Okay, Argsis really a parameter pack, not a type parameter, but for purposes of this discussion, we can treat it as if it were a type parameter.)

The fact that emplace_back's type parameter is named Args, yet it's still a universal reference, reinforces my earlier comment that it's the form of a universal reference that must be “ T&&”. There's no requirement that you use the name T. For example, the following template takes a universal reference, because the form (“ type &&”) is right, and param's type will be deduced (again, excluding the corner case where the caller explicitly specifies the type):

template // param is a

void someFunc( MyTemplateType&&param); // universal reference

I remarked earlier that autovariables can also be universal references. To be more precise, variables declared with the type auto&&are universal references, because type deduction takes place and they have the correct form (“ T&&”). autouniversal references are not as common as universal references used for function template parameters, but they do crop up from time to time in C++11. They crop up a lot more in C++14, because C++14 lambda expressions may declare auto&&parameters. For example, if you wanted to write a C++14 lambda to record the time taken in an arbitrary function invocation, you could do this:

auto timeFuncInvocation =

[]( auto&&func, auto&&... params) // C++14

{

start timer;

std::forward(func)( // invoke func

std::forward(params)... // on params

);

stop timer and record elapsed time;

};

If your reaction to the “ std::forwardblah blah blah )>” code inside the lambda is, “What the…?!”, that probably just means you haven't yet read Item 33. Don't worry about it. The important thing in this Item is the auto&&parameters that the lambda declares. funcis a universal reference that can be bound to any callable object, lvalue or rvalue. argsis zero or more universal references (i.e., a universal reference parameter pack) that can be bound to any number of objects of arbitrary types. The result, thanks to autouniversal references, is that timeFuncInvocationcan time pretty much any function execution. (For information on the difference between “any” and “pretty much any,” turn to Item 30.)

Bear in mind that this entire Item — the foundation of universal references — is a lie… er, an “abstraction.” The underlying truth is known as reference collapsing , a topic to which Item 28is dedicated. But the truth doesn't make the abstraction any less useful. Distinguishing between rvalue references and universal references will help you read source code more accurately (“Does that T&&I'm looking at bind to rvalues only or to everything?”), and it will avoid ambiguities when you communicate with your colleagues (“I'm using a universal reference here, not an rvalue reference.”). It will also allow you to make sense of Items 25and 26, which rely on the distinction. So embrace the abstraction. Revel in it. Just as Newton's laws of motion (which are technically incorrect) are typically just as useful as and easier to apply than Einstein's theory of general relativity (“the truth”), so is the notion of universal references normally preferable to working through the details of reference collapsing.

Things to Remember

• If a function template parameter has type T&&for a deduced type T, or if an object is declared using auto&&, the parameter or object is a universal reference.

• If the form of the type declaration isn't precisely type &&, or if type deduction does not occur, type &&denotes an rvalue reference.

• Universal references correspond to rvalue references if they're initialized with rvalues. They correspond to lvalue references if they're initialized with lvalues.

Item 25: Use std::moveon rvalue references, std::forwardon universal references.

Rvalue references bind only to objects that are candidates for moving. If you have an rvalue reference parameter, you know that the object it's bound to may be moved:

class Widget {

Widget( Widget&&rhs); // rhs definitely refers to an

… // object eligible for moving

};

That being the case, you'll want to pass such objects to other functions in a way that permits those functions to take advantage of the object's rvalueness. The way to do that is to cast parameters bound to such objects to rvalues. As Item 23explains, that's not only what std::movedoes, it's what it was created for:

class Widget {

public:

Widget(Widget&& rhs) // rhs is rvalue reference

: name( std::move(rhs.name)),

p( std::move(rhs.p))

{ … }

private:

std::string name;

std::shared_ptr p;

};

A universal reference, on the other hand (see Item 24), might be bound to an object that's eligible for moving. Universal references should be cast to rvalues only if they were initialized with rvalues. Item 23explains that this is precisely what std::forwarddoes:

class Widget {

public:

template

void setName(T&& newName) // newName is

{ name = std::forward(newName);} // universal reference

};

In short, rvalue references should be unconditionally cast to rvalues (via std::move) when forwarding them to other functions, because they're always bound to rvalues, and universal references should be conditionally cast to rvalues (via std::forward) when forwarding them, because they're only sometimes bound to rvalues.

Item 23explains that using std::forwardon rvalue references can be made to exhibit the proper behavior, but the source code is wordy, error-prone, and unidiomatic, so you should avoid using std::forwardwith rvalue references. Even worse is the idea of using std::movewith universal references, because that can have the effect of unexpectedly modifying lvalues (e.g., local variables):

class Widget {

public:

template

void setName( T&&newName) // universal reference

{ name = std::move(newName); } // compiles, but is

… // bad, bad, bad!

private:

std::string name;

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

Интервал:

Закладка:

Сделать

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

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


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

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

x