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

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

Интервал:

Закладка:

Сделать

void func( Widget&param);

The answer is reference collapsing . Yes, you are forbidden from declaring references to references, but compilers may produce them in particular contexts, template instantiation being among them. When compilers generate references to references, reference collapsing dictates what happens next.

There are two kinds of references (lvalue and rvalue), so there are four possible reference-reference combinations (lvalue to lvalue, lvalue to rvalue, rvalue to lvalue, and rvalue to rvalue). If a reference to a reference arises in a context where this is permitted (e.g., during template instantiation), the references collapse to a single reference according to this rule:

If either reference is an lvalue reference, the result is an lvalue reference. Otherwise (i.e., if both are rvalue references) the result is an rvalue reference.

In our example above, substitution of the deduced type Widget&into the template funcyields an rvalue reference to an lvalue reference, and the reference-collapsing rule tells us that the result is an lvalue reference.

Reference collapsing is a key part of what makes std::forwardwork. As explained in Item 25, std::forwardis applied to universal reference parameters, so a common use case looks like this:

template

void f(T&& fParam)

{

… // do some work

someFunc( std::forward(fParam)); // forward fParam to

} // someFunc

Because fParamis a universal reference, we know that the type parameter Twill encode whether the argument passed to f(i.e., the expression used to initialize fParam) was an lvalue or an rvalue. std::forward's job is to cast fParam(an lvalue) to an rvalue if and only if Tencodes that the argument passed to fwas an rvalue, i.e., if Tis a non-reference type.

Here's how std::forwardcan be implemented to do that:

template // in

TSS forward(typename // namespace

remove_reference::type& param) // std

{

return static_cast(param);

}

This isn't quite Standards-conformant (I've omitted a few interface details), but the differences are irrelevant for the purpose of understanding how std::forwardbehaves.

Suppose that the argument passed to f is an lvalue of type Widget. Twill be deduced as Widget&, and the call to std::forwardwill instantiate as std::forward. Plugging Widget&into the std::forwardimplementation yields this:

Widget&&& forward(typename

remove_reference< Widget&>::type& param)

{ return static_cast< Widget&&&>(param); }

The type trait std::remove_reference::typeyields Widget(see Item 9), so std::forwardbecomes:

Widget& && forward( Widget& param)

{ return static_cast(param); }

Reference collapsing is also applied to the return type and the cast, and the result is the final version of std::forwardfor the call:

Widget&forward( Widget&param) // still in

{ return static_cast< Widget&>(param); } // namespace std

As you can see, when an lvalue argument is passed to the function template f, std::forwardis instantiated to take and return an lvalue reference. The cast inside std::forwarddoes nothing, because param's type is already Widget&, so casting it to Widget&has no effect. An lvalue argument passed to std::forwardwill thus return an lvalue reference. By definition, lvalue references are lvalues, so passing an lvalue to std::forwardcauses an lvalue to be returned, just like it's supposed to.

Now suppose that the argument passed to fis an rvalue of type Widget. In this case, the deduced type for f's type parameter Twill simply be Widget. The call inside fto std::forwardwill thus be to std::forward. Substituting Widgetfor Tin the std::forwardimplementation gives this:

Widget&& forward(typename

remove_reference< Widget>::type& param)

{ return static_cast< Widget&&>(param); }

Applying std::remove_referenceto the non-reference type Widgetyields the same type it started with ( Widget), so std::forwardbecomes this:

Widget&& forward( Widget& param)

{ return static_cast(param); }

There are no references to references here, so there's no reference collapsing, and this is the final instantiated version of std::forwardfor the call.

Rvalue references returned from functions are defined to be rvalues, so in this case, std::forwardwill turn f's parameter fParam(an lvalue) into an rvalue. The end result is that an rvalue argument passed to fwill be forwarded to someFuncas an rvalue, which is precisely what is supposed to happen.

In C++14, the existence of std::remove_reference_tmakes it possible to implement std::forwarda bit more concisely:

template // C++14; still in

T&& forward( remove_reference_t& param) // namespace std

{

return static_cast(param);

}

Reference collapsing occurs in four contexts. The first and most common is template instantiation. The second is type generation for autovariables. The details are essentially the same as for templates, because type deduction for autovariables is essentially the same as type deduction for templates (see Item 2). Consider again this example from earlier in the Item:

template

void func(T&& param);

Widget widgetFactory(); // function returning rvalue

Widget w; // a variable (an lvalue)

func(w); // call func with lvalue; T deduced

// to be Widget&

func(widgetFactory()); // call func with rvalue; T deduced

// to be Widget

This can be mimicked in autoform. The declaration

auto&&w1 = w;

initializes w1with an lvalue, thus deducing the type Widget&for auto. Plugging Widget&in for autoin the declaration for w1yields this reference-to-reference code,

Widget& &&w1 = w;

which, after reference collapsing, becomes

Widget&w1 = w;

As a result, w1is an lvalue reference.

On the other hand, this declaration,

auto&&w2 = widgetFactory();

initializes w2with an rvalue, causing the non-reference type Widgetto be deduced for auto. Substituting Widgetfor autogives us this:

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

Интервал:

Закладка:

Сделать

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

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


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

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

x