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

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

Интервал:

Закладка:

Сделать

// myWidget1's type is Widget

decltype(auto)myWidget2 = cw; // decltype type deduction:

// myWidget2's type is

// const Widget&

But two things are bothering you, I know. One is the refinement to authAndAccessI mentioned, but have not yet described. Let's address that now.

Look again at the declaration for the C++14 version of authAndAccess:

template

decltype(auto) authAndAccess(Container& c, Index i);

The container is passed by lvalue-reference-to-non- const, because returning a reference to an element of the container permits clients to modify that container. But this means it's not possible to pass rvalue containers to this function. Rvalues can't bind to lvalue references (unless they're lvalue-references-to- const, which is not the case here).

Admittedly, passing an rvalue container to authAndAccessis an edge case. An rvalue container, being a temporary object, would typically be destroyed at the end of the statement containing the call to authAndAccess, and that means that a reference to an element in that container (which is typically what authAndAccesswould return) would dangle at the end of the statement that created it. Still, it could make sense to pass a temporary object to authAndAccess. A client might simply want to make a copy of an element in the temporary container, for example:

std::deque makeStringDeque(); // factory function

// make copy of 5th element of deque returned

// from makeStringDeque

auto s = authAndAccess(makeStringDeque(), 5);

Supporting such use means we need to revise the declaration for authAndAccessto accept both lvalues and rvalues. Overloading would work (one overload would declare an lvalue reference parameter, the other an rvalue reference parameter), but then we'd have two functions to maintain. A way to avoid that is to have authAndAccessemploy a reference parameter that can bind to lvalues and rvalues, and Item 24explains that that's exactly what universal references do. authAndAccesscan therefore be declared like this:

template // c is now a

decltype(auto) authAndAccess(Container &&c, // universal

Index i); // reference

In this template, we don't know what type of container we're operating on, and that means we're equally ignorant of the type of index objects it uses. Employing pass-by- value for objects of an unknown type generally risks the performance hit of unnecessary copying, the behavioral problems of object slicing (see Item 41), and the sting of our coworkers' derision, but in the case of container indices, following the example of the Standard Library for index values (e.g., in operator[]for std::string, std::vector, and std::deque) seems reasonable, so we'll stick with pass-by-value for them.

However, we need to update the template's implementation to bring it into accord with Item 25's admonition to apply std::forwardto universal references:

template // final

decltype(auto) // C++14

authAndAccess(Container&& c, Index i) // version

{

authenticateUser();

return std::forward(c )[i];

}

This should do everything we want, but it requires a C++14 compiler. If you don't have one, you'll need to use the C++11 version of the template. It's the same as its C++14 counterpart, except that you have to specify the return type yourself:

template // final

auto // C++11

authAndAccess(Container&& c, Index i) // version

-> decltype(std::forward(c)[i])

{

authenticateUser();

return std::forward(c)[i];

}

The other issue that's likely to be nagging at you is my remark at the beginning of this Item that decltype almost always produces the type you expect, that it rarely surprises. Truth be told, you're unlikely to encounter these exceptions to the rule unless you're a heavy-duty library implementer.

To fully understand decltype's behavior, you'll have to familiarize yourself with a few special cases. Most of these are too obscure to warrant discussion in a book like this, but looking at one lends insight into decltypeas well as its use.

Applying decltypeto a name yields the declared type for that name. Names are lvalue expressions, but that doesn't affect decltype's behavior. For lvalue expressions more complicated than names, however, decltypeensures that the type reported is always an lvalue reference. That is, if an lvalue expression other than a name has type T, decltypereports that type as T&. This seldom has any impact, because the type of most lvalue expressions inherently includes an lvalue reference qualifier. Functions returning lvalues, for example, always return lvalue references.

There is an implication of this behavior that is worth being aware of, however. In

int x = 0;

xis the name of a variable, so decltype(x)is int. But wrapping the name xin parentheses — “ (x)” — yields an expression more complicated than a name. Being a name, xis an lvalue, and C++ defines the expression (x)to be an lvalue, too. decltype((x))is therefore int&. Putting parentheses around a name can change the type that decltypereports for it!

In C++11, this is little more than a curiosity, but in conjunction with C++14's support for decltype(auto), it means that a seemingly trivial change in the way you write a returnstatement can affect the deduced type for a function:

decltype(auto)f1() {

int x = 0;

return x; // decltype(x) is int , so f1 returns int

}

decltype(auto)f2() {

int x = 0;

return (x); // decltype((x)) is int& , so f2 returns int&

}

Note that not only does f2have a different return type from f1, it's also returning a reference to a local variable! That's the kind of code that puts you on the express train to undefined behavior — a train you certainly don't want to be on.

The primary lesson is to pay very close attention when using decltype(auto). Seemingly insignificant details in the expression whose type is being deduced can affect the type that decltype(auto)reports. To ensure that the type being deduced is the type you expect, use the techniques described in Item 4.

At the same time, don't lose sight of the bigger picture. Sure, decltype(both alone and in conjunction with auto) may occasionally yield type-deduction surprises, but that's not the normal situation. Normally, decltypeproduces the type you expect.

This is especially true when decltypeis applied to names, because in that case, decltypedoes just what it sounds like: it reports that name's declared type.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x