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

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

Интервал:

Закладка:

Сделать

Widget makeWidget() // as before

{

Widget w;

return w;

}

compilers must either elide the copying of wor they must treat the function as if it were written like this:

Widget makeWidget() {

Widget w;

return std::move(w); // treat w as rvalue, because

} // no copy elision was performed

The situation is similar for by-value function parameters. They're not eligible for copy elision with respect to their function's return value, but compilers must treat them as rvalues if they're returned. As a result, if your source code looks like this,

WidgetmakeWidget( Widget w) // by-value parameter of same

{ // type as function's return

return w;

}

compilers must treat it as if it had been written this way:

Widget makeWidget(Widget w) {

return std::move(w); // treat w as rvalue

}

This means that if you use std::moveon a local object being returned from a function that's returning by value, you can't help your compilers (they have to treat the local object as an rvalue if they don't perform copy elision), but you can certainly hinder them (by precluding the RVO). There are situations where applying std::moveto a local variable can be a reasonable thing to do (i.e., when you're passing it to a function and you know you won't be using the variable any longer), but as part of a returnstatement that would otherwise qualify for the RVO or that returns a by-value parameter isn't among them.

Things to Remember

• Apply std::moveto rvalue references and std::forwardto universal references the last time each is used.

• Do the same thing for rvalue references and universal references being returned from functions that return by value.

• Never apply std::moveor std::forwardto local objects if they would otherwise be eligible for the return value optimization.

Item 26: Avoid overloading on universal references.

Suppose you need to write a function that takes a name as a parameter, logs the current date and time, then adds the name to a global data structure. You might come up with a function that looks something like this:

std::multiset names; // global data structure

void logAndAdd(const std::string& name) {

auto now = // get current time

std::chrono::system_clock::now();

log(now, "logAndAdd"); // make log entry

names.emplace(name); // add name to global data

} // structure; see Item 42

// for info on emplace

This isn't unreasonable code, but it's not as efficient as it could be. Consider three potential calls:

std::string petName("Darla");

logAndAdd( petName); // pass lvalue std::string

logAndAdd( std::string("Persephone")); // pass rvalue std::string

logAndAdd( "Patty Dog"); // pass string literal

In the first call, logAndAdd's parameter nameis bound to the variable petName. Within logAndAdd, nameis ultimately passed to names.emplace. Because nameis an lvalue, it is copied into names. There's no way to avoid that copy, because an lvalue ( petName) was passed into logAndAdd.

In the second call, the parameter nameis bound to an rvalue (the temporary std::stringexplicitly created from "Persephone"). nameitself is an lvalue, so it's copied into names, but we recognize that, in principle, its value could be moved into names. In this call, we pay for a copy, but we should be able to get by with only a move.

In the third call, the parameter nameis again bound to an rvalue, but this time it's to a temporary std::stringthat's implicitly created from "Patty Dog". As in the second call, name is copied into names, but in this case, the argument originally passed to logAndAddwas a string literal. Had that string literal been passed directly to emplace, there would have been no need to create a temporary std::stringat all. Instead, emplacewould have used the string literal to create the std::stringobject directly inside the std::multiset. In this third call, then, we're paying to copy a std::string, yet there's really no reason to pay even for a move, much less a copy.

We can eliminate the inefficiencies in the second and third calls by rewriting logAndAddto take a universal reference (see Item 24) and, in accord with Item 25, std::forwarding this reference to emplace. The results speak for themselves:

template

void logAndAdd( T&&name) {

auto now = std::chrono::system_clock::now();

log(now, "logAndAdd");

names.emplace( std::forward(name ));

}

std::string petName("Darla"); // as before

logAndAdd( petName); // as before, copy

// lvalue into multiset

logAndAdd( std::string("Persephone")); // move rvalue instead

// of copying it

logAndAdd( "Patty Dog"); // create std::string

// in multiset instead

// of copying a temporary

// std::string

Hurray, optimal efficiency!

Were this the end of the story, we could stop here and proudly retire, but I haven't told you that clients don't always have direct access to the names that logAndAddrequires. Some clients have only an index that logAndAdduses to look up the corresponding name in a table. To support such clients, logAndAddis overloaded:

std::string nameFromIdx(int idx); // return name

// corresponding to idx

void logAndAdd( int idx) // new overload

{

auto now = std::chrono::system_clock::now();

log(now, "logAndAdd");

names.emplace( nameFromIdx(idx));

}

Resolution of calls to the two overloads works as expected:

std::string petName("Darla"); // as before

logAndAdd(petName); // as before, these

logAndAdd(std::string("Persephone")); // calls all invoke

logAndAdd("Patty Dog"); // the T&& overload

logAndAdd(22); // calls int overload

Actually, resolution works as expected only if you don't expect too much. Suppose a client has a shortholding an index and passes that to logAndAdd:

short nameIdx;

… // give nameldx a value

logAndAdd(nameldx); // error!

The comment on the last line isn't terribly illuminating, so let me explain what happens here.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x