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 w;

using namespace std::placeholders;

auto compressRateB = std::bind(compress, w, _1);

Now, when we pass wto std::bind, it has to be stored for the later call to compress. It's stored inside the object compressRateB, but how is it stored — by value or by reference? It makes a difference, because if wis modified between the call to std::bindand a call to compressRateB, storing wby reference will reflect the changes, while storing it by value won't.

The answer is that it's stored by value, [14] std::bind always copies its arguments, but callers can achieve the effect of having an argument stored by reference by applying std::ref to it. The result of auto compressRateB = std::bind(compress, std::ref( w ) , _1); is that compressRateB acts as if it holds a reference to w , rather than a copy. but the only way to know that is to memorize how std::bindworks; there's no sign of it in the call to std::bind. Contrast that with a lambda approach, where whether wis captured by value or by reference is explicit:

auto compressRateL = // w is captured by

[ w](CompLevel lev) // value; lev is

{ return compress(w, lev); }; // passed by value

Equally explicit is how parameters are passed to the lambda. Here, it's clear that the parameter levis passed by value. Hence:

compressRate L(CompLevel::High); // arg is passed

// by value

But in the call to the object resulting from std::bind, how is the argument passed?

compressRate B(CompLevel::High); // how is arg

// passed?

Again, the only way to know is to memorize how std::bindworks. (The answer is that all arguments passed to bind objects are passed by reference, because the function call operator for such objects uses perfect forwarding.)

Compared to lambdas, then, code using std::bindis less readable, less expressive, and possibly less efficient. In C++14, there are no reasonable use cases for std::bind. In C++11, however, std::bind can be justified in two constrained situations:

Move capture.C++11 lambdas don't offer move capture, but it can be emulated through a combination of a lambda and std::bind. For details, consult Item 32, which also explains that in C++14, lambdas' support for init capture eliminates the need for the emulation.

Polymorphic function objects.Because the function call operator on a bind object uses perfect forwarding, it can accept arguments of any type (modulo the restrictions on perfect forwarding described in Item 30). This can be useful when you want to bind an object with a templatized function call operator. For example, given this class,

class PolyWidget {

public:

template

void operator()(const T& param);

};

std::bindcan bind a PolyWidgetas follows:

PolyWidget pw;

auto boundPW = std::bind(pw, _1);

boundPWcan then be called with different types of arguments:

boundPW(1930); // pass int to

// PolyWidget::operator()

boundPW(nullptr); // pass nullptr to

// PolyWidget::operator()

boundPW("Rosebud"); // pass string literal to

// PolyWidget::operator()

There is no way to do this with a C++11 lambda. In C++14, however, it's easily achieved via a lambda with an autoparameter:

auto boundPW = [pw](const auto& param) // C++14

{ pw(param); };

These are edge cases, of course, and they're transient edge cases at that, because compilers supporting C++14 lambdas are increasingly common.

When bindwas unofficially added to C++ in 2005, it was a big improvement over its 1998 predecessors. The addition of lambda support to C++11 rendered std::bindall but obsolete, however, and as of C++14, there are just no good use cases for it.

Things to Remember

• Lambdas are more readable, more expressive, and may be more efficient than using std::bind.

• In C++11 only, std::bindmay be useful for implementing move capture or for binding objects with templatized function call operators.

Chapter 7

The Concurrency API

One of C++11's great triumphs is the incorporation of concurrency into the language and library. Programmers familiar with other threading APIs (e.g., pthreads or Windows threads) are sometimes surprised at the comparatively Spartan feature set that C++ offers, but that's because a great deal of C++'s support for concurrency is in the form of constraints on compiler-writers. The resulting language assurances mean that for the first time in C++'s history, programmers can write multithreaded programs with standard behavior across all platforms. This establishes a solid foundation on which expressive libraries can be built, and the concurrency elements of the Standard Library (tasks, futures, threads, mutexes, condition variables, atomic objects, and more) are merely the beginning of what is sure to become an increasingly rich set of tools for the development of concurrent C++ software.

In the Items that follow, bear in mind that the Standard Library has two templates for futures: std::futureand std::shared_future. In many cases, the distinction is not important, so I often simply talk about futures , by which I mean both kinds.

Item 35: Prefer task-based programming to thread-based.

If you want to run a function doAsyncWorkasynchronously, you have two basic choices. You can create a std::threadand run doAsyncWorkon it, thus employing a thread-based approach:

int doAsyncWork();

std::threadt(doAsyncWork);

Or you can pass doAsyncWorkto std::async, a strategy known as task-based :

auto fut = std::async(doAsyncWork); // "fut" for "future"

In such calls, the function object passed to std::async(e.g., doAsyncWork) is considered a task .

The task-based approach is typically superior to its thread-based counterpart, and the tiny amount of code we've seen already demonstrates some reasons why. Here, doAsyncWorkproduces a return value, which we can reasonably assume the code invoking doAsyncWorkis interested in. With the thread-based invocation, there's no straightforward way to get access to it. With the task-based approach, it's easy, because the future returned from std::asyncoffers the getfunction. The getfunction is even more important if doAsyncWorkemits an exception, because getprovides access to that, too. With the thread-based approach, if doAsyncWorkthrows, the program dies (via a call to std::terminate).

A more fundamental difference between thread-based and task-based programming is the higher level of abstraction that task-based embodies. It frees you from the details of thread management, an observation that reminds me that I need to summarize the three meanings of “thread” in concurrent C++ software:

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

Интервал:

Закладка:

Сделать

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

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


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

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

x