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

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

Интервал:

Закладка:

Сделать

intx1; // potentially uninitialized

autox2; // error! initializer required

autox3 = 0; // fine, x's value is well-defined

Said highway lacks the potholes associated with declaring a local variable whose value is that of a dereferenced iterator:

template // as before

void dwim(It b, It e) {

while (b != e) {

autocurrValue = *b;

}

}

And because autouses type deduction (see Item 2), it can represent types known only to compilers:

autoderefUPLess = // comparison func.

[](const std::unique_ptr& p1, // for Widgets

const std::unique_ptr& p2) // pointed to by

{ return *p1 < *p2; }; // std::unique_ptrs

Very cool. In C++14, the temperature drops further, because parameters to lambda expressions may involve auto:

auto derefLess = // C++14 comparison

[](const auto& p1, // function for

const auto& p2) // values pointed

{ return *p1 < *p2; }; // to by anything

// pointer-like

Coolness notwithstanding, perhaps you're thinking we don't really need autoto declare a variable that holds a closure, because we can use a std::functionobject. It's true, we can, but possibly that's not what you were thinking. And maybe now you're thinking “What's a std::functionobject?” So let's clear that up.

std::functionis a template in the C++11 Standard Library that generalizes the idea of a function pointer. Whereas function pointers can point only to functions, however, std::functionobjects can refer to any callable object, i.e., to anything that can be invoked like a function. Just as you must specify the type of function to point to when you create a function pointer (i.e., the signature of the functions you want to point to), you must specify the type of function to refer to when you create a std::functionobject. You do that through std::function's template parameter. For example, to declare a std::functionobject named functhat could refer to any callable object acting as if it had this signature,

bool(const std::unique_ptr&, // C++11 signature for

const std::unique_ptr&) // std::unique_ptr

// comparison function

you'd write this:

std::function&,

const std::unique_ptr&)> func;

Because lambda expressions yield callable objects, closures can be stored in std::functionobjects. That means we could declare the C++11 version of derefUPLesswithout using autoas follows:

std::function&,

const std::unique_ptr&)>

derefUPLess = [](const std::unique_ptr& p1,

const std::unique_ptr& p2)

{ return *p1 < *p2; };

It's important to recognize that even setting aside the syntactic verbosity and need to repeat the parameter types, using std::functionis not the same as using auto. An auto-declared variable holding a closure has the same type as the closure, and as such it uses only as much memory as the closure requires. The type of a std::function-declared variable holding a closure is an instantiation of the std::functiontemplate, and that has a fixed size for any given signature. This size may not be adequate for the closure it's asked to store, and when that's the case, the std::functionconstructor will allocate heap memory to store the closure. The result is that the std::functionobject typically uses more memory than the auto-declared object. And, thanks to implementation details that restrict inlining and yield indirect function calls, invoking a closure via a std::functionobject is almost certain to be slower than calling it via an auto-declared object. In other words, the std::functionapproach is generally bigger and slower than the autoapproach, and it may yield out-of-memory exceptions, too. Plus, as you can see in the examples above, writing “ auto” is a whole lot less work than writing the type of the std::functioninstantiation. In the competition between autoand std::functionfor holding a closure, it's pretty much game, set, and match for auto. (A similar argument can be made for autoover std::functionfor holding the result of calls to std::bind, but in Item 34, I do my best to convince you to use lambdas instead of std::bind, anyway.)

The advantages of autoextend beyond the avoidance of uninitialized variables, verbose variable declarations, and the ability to directly hold closures. One is the ability to avoid what I call problems related to “type shortcuts.” Here's something you've probably seen — possibly even written:

std::vector v;

unsignedsz = v.size();

The official return type of v.size()is std::vector::size_type, but few developers are aware of that. std::vector::size_typeis specified to be an unsigned integral type, so a lot of programmers figure that unsigned is good enough and write code such as the above. This can have some interesting consequences. On 32-bit Windows, for example, both unsignedand std::vector::size_typeare the same size, but on 64-bit Windows, unsignedis 32 bits, while std::vector::size_typeis 64 bits. This means that code that works under 32-bit Windows may behave incorrectly under 64-bit Windows, and when porting your application from 32 to 64 bits, who wants to spend time on issues like that?

Using autoensures that you don't have to:

autosz = v.size(); // sz's type is std::vector::size_type

Still unsure about the wisdom of using auto? Then consider this code:

std::unordered_map m;

for (const std::pair& p : m) {

… // do something with p

}

This looks perfectly reasonable, but there's a problem. Do you see it?

Recognizing what's amiss requires remembering that the key part of a s td::unordered_mapis const, so the type of std::pairin the hash table (which is what a std::unordered_mapis) isn't std::pair, it's std::pair < const std::string, int>. But that's not the type declared for the variable pin the loop above. As a result, compilers will strive to find a way to convert std::pairobjects (i.e., what's in the hash table) to s td::pairobjects (the declared type for p). They'll succeed by creating a temporary object of the type that p wants to bind to by copying each object in m, then binding the reference pto that temporary object. At the end of each loop iteration, the temporary object will be destroyed. If you wrote this loop, you'd likely be surprised by this behavior, because you'd almost certainly intend to simply bind the reference pto each element in m.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x