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

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

Интервал:

Закладка:

Сделать

}

This is the form you'll see in, among other places, the standard containers' emplacement functions (see Item 42) and the smart pointer factory functions, std::make_sharedand std::make_unique(see Item 21).

Given our target function fand our forwarding function fwd, perfect forwarding fails if calling fwith a particular argument does one thing, but calling fwdwith the same argument does something different:

f( expression ); // if this does one thing,

fwd( expression ); // but this does something else, fwd fails

// to perfectly forward expression to f

Several kinds of arguments lead to this kind of failure. Knowing what they are and how to work around them is important, so let's tour the kinds of arguments that can't be perfect-forwarded.

Braced initializers

Suppose f is declared like this:

void f(const std::vector& v);

In that case, calling fwith a braced initializer compiles,

f( { 1, 2, 3 }); // fine, "{1, 2, 3}" implicitly

// converted to std::vector

but passing the same braced initializer to fwddoesn't compile:

fwd( { 1, 2, 3 }); // error! doesn't compile

That's because the use of a braced initializer is a perfect forwarding failure case.

All such failure cases have the same cause. In a direct call to f(such as f({ l, 2, 3 })), compilers see the arguments passed at the call site, and they see the types of the parameters declared by f. They compare the arguments at the call site to the parameter declarations to see if they're compatible, and, if necessary, they perform implicit conversions to make the call succeed. In the example above, they generate a temporary std::vectorobject from { 1, 2, 3 }so that f's parameter vhas a std::vectorobject to bind to.

When calling findirectly through the forwarding function template fwd, compilers no longer compare the arguments passed at fwd's call site to the parameter declarations in f. Instead, they deduce the types of the arguments being passed to fwd, and they compare the deduced types to f's parameter declarations. Perfect forwarding fails when either of the following occurs:

Compilers are unable to deduce a typefor one or more of fwd's parameters. In this case, the code fails to compile.

Compilers deduce the “wrong” typefor one or more of fwd's parameters. Here, “wrong” could mean that fwd's instantiation won't compile with the types that were deduced, but it could also mean that the call to fusing fwd's deduced types behaves differently from a direct call to fwith the arguments that were passed to fwd. One source of such divergent behavior would be if fwere an overloaded function name, and, due to “incorrect” type deduction, the overload of fcalled inside fwdwere different from the overload that would be invoked if fwere called directly.

In the “ fwd({ 1, 2, 3 })” call above, the problem is that passing a braced initializer to a function template parameter that's not declared to be a std::initializer_listis decreed to be, as the Standard puts it, a “non-deduced context.” In plain English, that means that compilers are forbidden from deducing a type for the expression { 1, 2, 3 }in the call to fwd, because fwd's parameter isn't declared to be a std::initializer_list. Being prevented from deducing a type for fwd's parameter, compilers must understandably reject the call.

Interestingly, Item 2explains that type deduction succeeds for autovariables initialized with a braced initializer. Such variables are deemed to be std::initializer_listobjects, and this affords a simple workaround for cases where the type the forwarding function should deduce is a std::initializer_list— declare a local variable using auto, then pass the local variable to the forwarding function:

auto il = { 1, 2, 3 }; // il's type deduced to be

// std::initializer_list

fwd(il); // fine, perfect-forwards il to f

0or NULLas null pointers

Item 8explains that when you try to pass 0or NULLas a null pointer to a template, type deduction goes awry, deducing an integral type (typically int) instead of a pointer type for the argument you pass. The result is that neither 0nor NULLcan be perfect-forwarded as a null pointer. The fix is easy, however: pass nullptrinstead of 0or NULL. For details, consult Item 8.

Declaration-only integral static constdata members

As a general rule, there's no need to define integral static constdata members in classes; declarations alone suffice. That's because compilers perform const propagation on such members' values, thus eliminating the need to set aside memory for them. For example, consider this code:

class Widget {

public:

static const std::size_t MinVals = 28;// MinVals' declaration

};

… // no defn. for MinVals

std::vector widgetData;

widgetData.reserve( Widget::MinVals); // use of MinVals

Here, we're using Widget::MinVals(henceforth simply MinVals) to specify widgetData's initial capacity, even though MinValslacks a definition. Compilers work around the missing definition (as they are required to do) by plopping the value 28 into all places where MinValsis mentioned. The fact that no storage has been set aside for MinVals' value is unproblematic. If MinVals' address were to be taken (e.g., if somebody created a pointer to MinVals), then MinValswould require storage (so that the pointer had something to point to), and the code above, though it would compile, would fail at link-time until a definition for MinValswas provided.

With that in mind, imagine that f(the function fwdforwards its argument to) is declared like this:

void f(std::size_t val);

Calling fwith MinValsis fine, because compilers will just replace MinValswith its value:

f( Widget::MinVals); // fine, treated as "f(28)"

Alas, things may not go so smoothly if we try to call fthrough fwd:

fwd( Widget::MinVals); // error! shouldn't link

This code will compile, but it shouldn't link. If that reminds you of what happens if we write code that takes MinVals' address, that's good, because the underlying problem is the same.

Although nothing in the source code takes MinVals' address, fwd's parameter is a universal reference, and references, in the code generated by compilers, are usually treated like pointers. In the program's underlying binary code (and on the hardware), pointers and references are essentially the same thing. At this level, there's truth to the adage that references are simply pointers that are automatically dereferenced. That being the case, passing MinValsby reference is effectively the same as passing it by pointer, and as such, there has to be some memory for the pointer to point to. Passing integral static constdata members by reference, then, generally requires that they be defined, and that requirement can cause code using perfect forwarding to fail where the equivalent code without perfect forwarding succeeds.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x