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

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

Интервал:

Закладка:

Сделать

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

processWidget(spw, computePriority()); // correct, but not

// optimal; see below

This works, because a std::shared_ptrassumes ownership of the raw pointer passed to its constructor, even if that constructor yields an exception. In this example, if spw's constructor throws an exception (e.g., due to an inability to dynamically allocate memory for a control block), it's still guaranteed that cusDelwill be invoked on the pointer resulting from “ new Widget”.

The minor performance hitch is that in the exception-unsafe call, we're passing an rvalue to processWidget,

processWidget(

std::shared_ptr(new Widget, cusDel), // arg is rvalue

computePriority()

);

but in the exception-safe call, we're passing an lvalue:

processWidget( spw, computePriority()); // arg is lvalue

Because processWidget's std::shared_ptrparameter is passed by value, construction from an rvalue entails only a move, while construction from an lvalue requires a copy. For std::shared_ptr, the difference can be significant, because copying a std::shared_ptrrequires an atomic increment of its reference count, while moving a std::shared_ptrrequires no reference count manipulation at all. For the exception-safe code to achieve the level of performance of the exception-unsafe code, we need to apply std::moveto spwto turn it into an rvalue (see Item 23):

processWidget( std::move(spw ), // both efficient and

computePriority()); // exception safe

That's interesting and worth knowing, but it's also typically irrelevant, because you'll rarely have a reason not to use a makefunction. And unless you have a compelling reason for doing otherwise, using a makefunction is what you should do.

Things to Remember

• Compared to direct use of new, make functions eliminate source code duplication, improve exception safety, and, for std::make_sharedand std::allocate_shared, generate code that's smaller and faster.

• Situations where use of make functions is inappropriate include the need to specify custom deleters and a desire to pass braced initializers.

• For std::shared_ptrs, additional situations where make functions may be ill-advised include (1) classes with custom memory management and (2) systems with memory concerns, very large objects, and std::weak_ptrs that outlive the corresponding std::shared_ptrs.

Item 22: When using the Pimpl Idiom, define special member functions in the implementation file.

If you've ever had to combat excessive build times, you're familiar with the Pimpl (“pointer to implementation”) Idiom . That's the technique whereby you replace the data members of a class with a pointer to an implementation class (or struct), put the data members that used to be in the primary class into the implementation class, and access those data members indirectly through the pointer. For example, suppose Widgetlooks like this:

class Widget { // in header "widget.h"

public:

Widget();

private:

std::string name;

std::vector data;

Gadget g1, g2, g3; // Gadget is some user-

}; // defined type

Because Widget's data members are of types std::string, std::vector, and Gadget, headers for those types must be present for Widgetto compile, and that means that Widgetclients must #include , , and gadget.h. Those headers increase the compilation time for Widgetclients, plus they make those clients dependent on the contents of the headers. If a header's content changes, Widgetclients must recompile. The standard headers and don't change very often, but it could be that gadget.his subject to frequent revision.

Applying the Pimpl Idiom in C++98 could have Widgetreplace its data members with a raw pointer to a struct that has been declared, but not defined:

class Widget { // still in header "widget.h"

public:

Widget();

~Widget(); // dtor is needed-see below

private:

struct Impl; // declare implementation struct

Impl *pImpl; // and pointer to it

};

Because Widgetno longer mentions the types std::string, std::vector, and Gadget, Widgetclients no longer need to #includethe headers for these types. That speeds compilation, and it also means that if something in these headers changes, Widgetclients are unaffected.

A type that has been declared, but not defined, is known as an incomplete type . Widget::Implis such a type. There are very few things you can do with an incomplete type, but declaring a pointer to it is one of them. The Pimpl Idiom takes advantage of that.

Part 1 of the Pimpl Idiom is the declaration of a data member that's a pointer to an incomplete type. Part 2 is the dynamic allocation and deallocation of the object that holds the data members that used to be in the original class. The allocation and deallocation code goes in the implementation file, e.g., for Widget, in widget.cpp:

#include "widget.h" // in impl.file "widget.cpp"

#include "gadget.h"

#include

#include

struct Widget::Impl { // definition of Widget::Impl

std::string name; // with data members formerly

std::vector data; // in Widget

Gadget g1, g2, g3;

};

Widget::Widget() // allocate data members for

: pImpl( new Impl) // this Widget object

{}

Widget::~Widget() // destroy data members for

{ delete pImpl;} // this object

Here I'm showing #includedirectives to make clear that the overall dependencies on the headers for std::string, std::vector, and Gadgetcontinue to exist. However, these dependencies have been moved from widget.h(which is visible to and used by Widgetclients) to widget.cpp(which is visible to and used only by the Widgetimplementer). I've also highlighted the code that dynamically allocates and deallocates the Implobject. The need to deallocate this object when a Widgetis destroyed is what necessitates the Widgetdestructor.

But I've shown you C++98 code, and that reeks of a bygone millennium. It uses raw pointers and raw newand raw deleteand it's all just so…raw. This chapter is built on the idea that smart pointers are preferable to raw pointers, and if what we want is to dynamically allocate a Widget::Implobject inside the Widgetconstructor and have it destroyed at the same time the Widgetis, std::unique_ptr(see Item 18) is precisely the tool we need. Replacing the raw pImplpointer with a std::unique_ptryields this code for the header file,

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

Интервал:

Закладка:

Сделать

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

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


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

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

x