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

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

Интервал:

Закладка:

Сделать
An objects control block is set up by the function creating the first - фото 3

An object's control block is set up by the function creating the first std::shared_ptrto the object. At least that's what's supposed to happen. In general, it's impossible for a function creating a std::shared_ptrto an object to know whether some other std::shared_ptralready points to that object, so the following rules for control block creation are used:

std::make_shared (see Item 21) always creates a control block. It manufactures a new object to point to, so there is certainly no control block for that object at the time std::make_sharedis called.

A control block is created when a std::shared_ptr is constructed from a unique-ownership pointer (i.e., a std::unique_ptr or std::auto_ptr ). Unique-ownership pointers don't use control blocks, so there should be no control block for the pointed-to object. (As part of its construction, the std::shared_ptrassumes ownership of the pointed-to object, so the unique-ownership pointer is set to null.)

When a std::shared_ptr constructor is called with a raw pointer, it creates a control block. If you wanted to create a std::shared_ptrfrom an object that already had a control block, you'd presumably pass a std::shared_ptror a std::weak_ptr(see Item 20) as a constructor argument, not a raw pointer. std::shared_ptrconstructors taking std::shared_ptrs or std::weak_ptrs as constructor arguments don't create new control blocks, because they can rely on the smart pointers passed to them to point to any necessary control blocks.

A consequence of these rules is that constructing more than one std::shared_ptrfrom a single raw pointer gives you a complimentary ride on the particle accelerator of undefined behavior, because the pointed-to object will have multiple control blocks. Multiple control blocks means multiple reference counts, and multiple reference counts means the object will be destroyed multiple times (once for each reference count). That means that code like this is bad, bad, bad:

auto pw= new Widget; // pw is raw ptr

std::shared_ptr spw1( pw, loggingDel); // create control

// block for *pw

std::shared_ptr spw2( pw, loggingDel); // create 2nd

// control block

// for *pw!

The creation of the raw pointer pwto a dynamically allocated object is bad, because it runs contrary to the advice behind this entire chapter: to prefer smart pointers to raw pointers. (If you've forgotten the motivation for that advice, refresh your memory on page 115.) But set that aside. The line creating pwis a stylistic abomination, but at least it doesn't cause undefined program behavior.

Now, the constructor for spw1is called with a raw pointer, so it creates a control block (and thereby a reference count) for what's pointed to. In this case, that's *pw(i.e., the object pointed to by pw). In and of itself, that's okay, but the constructor for spw2is called with the same raw pointer, so it also creates a control block (hence a reference count) for *pw. *pwthus has two reference counts, each of which will eventually become zero, and that will ultimately lead to an attempt to destroy *pwtwice. The second destruction is responsible for the undefined behavior.

There are at least two lessons regarding std::shared_ptruse here. First, try to avoid passing raw pointers to a std::shared_ptrconstructor. The usual alternative is to use std::make_shared(see Item 21), but in the example above, we're using custom deleters, and that's not possible with std::make_shared. Second, if you must pass a raw pointer to a std::shared_ptrconstructor, pass the result of new directly instead of going through a raw pointer variable. If the first part of the code above were rewritten like this,

std::shared_ptr spw1( new Widget, // direct use of new

loggingDel);

it'd be a lot less tempting to create a second std::shared_ptrfrom the same raw pointer. Instead, the author of the code creating spw2would naturally use spw1as an initialization argument (i.e., would call the std::shared_ptrcopy constructor), and that would pose no problem whatsoever:

std::shared_ptr spw2( spw1); // spw2 uses same

// control block as spw1

An especially surprising way that using raw pointer variables as std::shared_ptrconstructor arguments can lead to multiple control blocks involves the thispointer. Suppose our program uses std::shared_ptrs to manage Widgetobjects, and we have a data structure that keeps track of Widgets that have been processed:

std::vector< std::shared_ptr> processedWidgets;

Further suppose that Widgethas a member function that does the processing:

class Widget {

public:

void process();

};

Here's a reasonable-looking approach for Widget::process:

void Widget::process() {

… // process the Widget

processedWidgets.emplace_back( this); // add it to list of

} // processed Widgets;

// this is wrong!

The comment about this being wrong says it all — or at least most of it. (The part that's wrong is the passing of this, not the use of emplace_back. If you're not familiar with emplace_back, see Item 42.) This code will compile, but it's passing a raw pointer ( this) to a container of std::shared_ptrs. The std::shared_ptrthus constructed will create a new control block for the pointed-to Widget(*this). That doesn't sound harmful until you realize that if there are std::shared_ptrs outside the member function that already point to that Widget, it's game, set, and match for undefined behavior.

The std::shared_ptrAPI includes a facility for just this kind of situation. It has probably the oddest of all names in the Standard C++ Library: std::enable_shared_from_this. That's a template for a base class you inherit from if you want a class managed by std::shared_ptrs to be able to safely create a std::shared_ptrfrom a thispointer. In our example, Widgetwould inherit from std::enable_shared_from_thisas follows:

class Widget : public std::enable_shared_from_this{

public:

void process();

};

As I said, std::enable_shared_from_thisis a base class template. Its type parameter is always the name of the class being derived, so Widgetinherits from std::enable_shared_from_this. If the idea of a derived class inheriting from a base class templatized on the derived class makes your head hurt, try not to think about it. The code is completely legal, and the design pattern behind it is so well established, it has a standard name, albeit one that's almost as odd as std::enable_shared_from_this. The name is The Curiously Recurring Template Pattern (CRTP) . If you'd like to learn more about it, unleash your search engine, because here we need to get back to std::enable_shared_from_this.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x