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

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

Интервал:

Закладка:

Сделать

Now suppose we have a function to compute the relevant priority,

int computePriority();

and we use that in a call to processWidgetthat uses newinstead of std::make_shared:

processWidget(std::shared_ptr(new Widget), // potential

computePriority()); // resource

// leak!

As the comment indicates, this code could leak the Widgetconjured up by new. But how? Both the calling code and the called function are using std::shared_ptrs, and std::shared_ptrs are designed to prevent resource leaks. They automatically destroy what they point to when the last std::shared_ptrpointing there goes away. If everybody is using std::shared_ptrs everywhere, how can this code leak?

The answer has to do with compilers' translation of source code into object code. At runtime, the arguments for a function must be evaluated before the function can be invoked, so in the call to processWidget, the following things must occur before processWidgetcan begin execution:

• The expression “ new Widget” must be evaluated, i.e., a Widgetmust be created on the heap.

• The constructor for the std::shared_ptrresponsible for managing the pointer produced by newmust be executed.

computePrioritymust run.

Compilers are not required to generate code that executes them in this order. “ new Widget” must be executed before the std::shared_ptrconstructor may be called, because the result of that newis used as an argument to that constructor, but computePrioritymay be executed before those calls, after them, or, crucially, between them. That is, compilers may emit code to execute the operations in this order:

• Perform “ new Widget”.

• Execute computePriority.

• Run std::shared_ptrconstructor.

If such code is generated and, at runtime, computePriorityproduces an exception, the dynamically allocated Widgetfrom Step 1 will be leaked, because it will never be stored in the std::shared_ptrthat's supposed to start managing it in Step 3.

Using std::make_sharedavoids this problem. Calling code would look like this:

processWidget( std::make_shared(), // no potential

computePriority()); // resource leak

At runtime, either std::make_sharedor computePrioritywill be called first. If it's std::make_shared, the raw pointer to the dynamically allocated Widgetis safely stored in the returned std::shared_ptrbefore computePriorityis called. If computePrioritythen yields an exception, the std::shared_ptrdestructor will see to it that the Widgetit owns is destroyed. And if computePriorityis called first and yields an exception, std::make_sharedwill not be invoked, and there will hence be no dynamically allocated Widgetto worry about.

If we replace std::shared_ptrand std::make_sharedwith std::unique_ptrand std::make_unique, exactly the same reasoning applies. Using std::make_uniqueinstead of newis thus just as important in writing exception-safe code as using std::make_shared.

A special feature of std::make_shared(compared to direct use of new) is improved efficiency. Using std::make_sharedallows compilers to generate smaller, faster code that employs leaner data structures. Consider the following direct use of new:

std::shared_ptr spw(new Widget);

It's obvious that this code entails a memory allocation, but it actually performs two. Item 19explains that every std::shared_ptrpoints to a control block containing, among other things, the reference count for the pointed-to object. Memory for this control block is allocated in the std::shared_ptrconstructor. Direct use of new, then, requires one memory allocation for the Widgetand a second allocation for the control block.

If std::make_sharedis used instead,

auto spw = std::make_shared();

one allocation suffices. That's because std::make_sharedallocates a single chunk of memory to hold both the Widgetobject and the control block. This optimization reduces the static size of the program, because the code contains only one memory allocation call, and it increases the speed of the executable code, because memory is allocated only once. Furthermore, using std::make_sharedobviates the need for some of the bookkeeping information in the control block, potentially reducing the total memory footprint for the program.

The efficiency analysis for std::make_sharedis equally applicable to std::allocate_shared, so the performance advantages of s td::make_sharedextend to that function, as well.

The arguments for preferring makefunctions over direct use of neware strong ones. Despite their software engineering, exception safety, and efficiency advantages, however, this Item's guidance is to prefer the makefunctions, not to rely on them exclusively. That's because there are circumstances where they can't or shouldn't be used.

For example, none of the makefunctions permit the specification of custom deleters (see Items 18and 19), but both std::unique_ptrand std::shared_ptrhave constructors that do. Given a custom deleter for a Widget,

auto widgetDeleter = [](Widget* pw) { … };

creating a smart pointer using it is straightforward using new:

std::unique_ptr

upw( new Widget, widgetDeleter);

std::shared_ptr spw( new Widget, widgetDeleter);

There's no way to do the same thing with a makefunction.

A second limitation of makefunctions stems from a syntactic detail of their implementations. Item 7explains that when creating an object whose type overloads constructors both with and without std::initializer_listparameters, creating the object using braces prefers the std::initializer_listconstructor, while creating the object using parentheses calls the non- std::initializer_listconstructor. The makefunctions perfect-forward their parameters to an object's constructor, but do they do so using parentheses or using braces? For some types, the answer to this question makes a big difference. For example, in these calls,

auto upv = std::make_unique>(10, 20);

auto spv = std::make_shared>(10, 20);

do the resulting smart pointers point to std::vectors with 10 elements, each of value 20, or to std::vectors with two elements, one with value 10 and the other with value 20? Or is the result indeterminate?

The good news is that it's not indeterminate: both calls create std::vectors of size 10 with all values set to 20. That means that within the makefunctions, the perfect forwarding code uses parentheses, not braces. The bad news is that if you want to construct your pointed-to object using a braced initializer, you must use newdirectly. Using a makefunction would require the ability to perfect-forward a braced initializer, but, as Item 30explains, braced initializers can't be perfect-forwarded. However, Item 30also describes a workaround: use autotype deduction to create a std::initializer_listobject from a braced initializer (see Item 2), then pass the auto-created object through the makefunction:

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

Интервал:

Закладка:

Сделать

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

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


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

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

x