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

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

Интервал:

Закладка:

Сделать

There are two logAndAddoverloads. The one taking a universal reference can deduce T to be short, thus yielding an exact match. The overload with an intparameter can match the shortargument only with a promotion. Per the normal overload resolution rules, an exact match beats a match with a promotion, so the universal reference overload is invoked.

Within that overload, the parameter nameis bound to the short that's passed in. nameis then std::forwarded to the emplace member function on names(a std::multiset), which, in turn, dutifully forwards it to the std::stringconstructor. There is no constructor for std::stringthat takes a short, so the std::stringconstructor call inside the call to multiset::emplaceinside the call to logAndAddfails. All because the universal reference overload was a better match for a shortargument than an int.

Functions taking universal references are the greediest functions in C++. They instantiate to create exact matches for almost any type of argument. (The few kinds of arguments where this isn't the case are described in Item 30.) This is why combining overloading and universal references is almost always a bad idea: the universal reference overload vacuums up far more argument types than the developer doing the overloading generally expects.

An easy way to topple into this pit is to write a perfect forwarding constructor. A small modification to the logAndAddexample demonstrates the problem. Instead of writing a free function that can take either a std::string or an index that can be used to look up a std::string, imagine a class Personwith constructors that do the same thing:

class Person {

public:

template

explicit Person(T&& n) // perfect forwarding ctor;

: name(std::forward(n)) {} // initializes data member

explicit Person(int idx) // int ctor

: name(nameFromIdx(idx)) {}

private:

std::string name;

};

As was the case with logAndAdd, passing an integral type other than int(e.g., std::size_t, short, long, etc.) will call the universal reference constructor overload instead of the int overload, and that will lead to compilation failures. The problem here is much worse, however, because there's more overloading present in Personthan meets the eye. Item 17explains that under the appropriate conditions, C++ will generate both copy and move constructors, and this is true even if the class contains a templatized constructor that could be instantiated to produce the signature of the copy or move constructor. If the copy and move constructors for Personare thus generated, Personwill effectively look like this:

class Person {

public:

template // perfect forwarding ctor

explicit Person(T&& n)

: name(std::forward(n)) {}

explicit Person(int idx); // int ctor

Person(const Person& rhs);// copy ctor

// (compiler-generated)

Person(Person&& rhs); // move ctor

… // (compiler-generated)

};

This leads to behavior that's intuitive only if you've spent so much time around compilers and compiler-writers, you've forgotten what it's like to be human:

Person p("Nancy");

auto cloneOfP(p); // create new Person from p;

// this won't compile!

Here we're trying to create a Personfrom another Person, which seems like about as obvious a case for copy construction as one can get. ( p's an lvalue, so we can banish any thoughts we might have about the “copying” being accomplished through a move operation.) But this code won't call the copy constructor. It will call the perfect- forwarding constructor. That function will then try to initialize Person's std::stringdata member with a Personobject ( p). std::stringhaving no constructor taking a Person, your compilers will throw up their hands in exasperation, possibly punishing you with long and incomprehensible error messages as an expression of their displeasure.

“Why,” you might wonder, “does the perfect-forwarding constructor get called instead of the copy constructor? We're initializing a Personwith another Person!” Indeed we are, but compilers are sworn to uphold the rules of C++, and the rules of relevance here are the ones governing the resolution of calls to overloaded functions.

Compilers reason as follows. cloneOfPis being initialized with a non -constlvalue ( p), and that means that the templatized constructor can be instantiated to take a non- constlvalue of type Person. After such instantiation, the Personclass looks like this:

class Person {

public:

explicit Person(Person& n) // instantiated from

: name(std::forward(n)) {} // perfect-forwarding

// template

explicit Person(int idx); // as before

Person(const Person& rhs); // copy ctor

… // (compiler-generated)

};

In the statement,

auto cloneOfP(p);

pcould be passed to either the copy constructor or the instantiated template. Calling the copy constructor would require adding constto pto match the copy constructor's parameter's type, but calling the instantiated template requires no such addition. The overload generated from the template is thus a better match, so compilers do what they're designed to do: generate a call to the better-matching function. “Copying” non- constlvalues of type Personis thus handled by the perfect-forwarding constructor, not the copy constructor.

If we change the example slightly so that the object to be copied is const, we hear an entirely different tune:

constPerson cp("Nancy"); // object is now const

auto cloneOfP(cp); // calls copy constructor!

Because the object to be copied is now const, it's an exact match for the parameter taken by the copy constructor. The templatized constructor can be instantiated to have the same signature,

class Person {

public:

explicit Person(const Person& n);// instantiated from

// template

Person(const Person& rhs); // copy ctor

// (compiler-generated)

};

but this doesn't matter, because one of the overload-resolution rules in C++ is that in situations where a template instantiation and a non-template function (i.e., a “normal” function) are equally good matches for a function call, the normal function is preferred. The copy constructor (a normal function) thereby trumps an instantiated template with the same signature.

(If you're wondering why compilers generate a copy constructor when they could instantiate a templatized constructor to get the signature that the copy constructor would have, review Item 17.)

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

Интервал:

Закладка:

Сделать

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

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


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

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

x