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

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

Интервал:

Закладка:

Сделать

template

typename... Ts> // types of arguments to use

void doSomeWork(Ts&&... params) {

create local T object from params ...

}

There are two ways to turn the line of pseudocode into real code (see Item 25for information about std::forward):

T localObject (std::forward(params)... ); // using parens

T localObject {std::forward(params)... }; // using braces

So consider this calling code:

std::vector v;

doSomeWork>(10, 20);

If doSomeWorkuses parentheses when creating localObject, the result is a std::vectorwith 10 elements. If doSomeWorkuses braces, the result is a std::vectorwith 2 elements. Which is correct? The author of doSomeWorkcan't know. Only the caller can.

This is precisely the problem faced by the Standard Library functions std::make_uniqueand std::make_shared(see Item 21). These functions resolve the problem by internally using parentheses and by documenting this decision as part of their interfaces. [1] More flexible designs — ones that permit callers to determine whether parentheses or braces should be used in functions generated from a template — are possible. For details, see the 5 June 2013 entry of Andrzej's C++ blog , “ Intuitive interface — Part I . ”

Things to Remember

• Braced initialization is the most widely usable initialization syntax, it prevents narrowing conversions, and it's immune to C++'s most vexing parse.

• During constructor overload resolution, braced initializers are matched to std::initializer_listparameters if at all possible, even if other constructors offer seemingly better matches.

• An example of where the choice between parentheses and braces can make a significant difference is creating a std::vector< numeric type >with two arguments.

• Choosing between parentheses and braces for object creation inside templates can be challenging.

Item 8: Prefer nullptrto 0and NULL.

So here's the deal: the literal 0is an int, not a pointer. If C++ finds itself looking at 0in a context where only a pointer can be used, it'll grudgingly interpret 0as a null pointer, but that's a fallback position. C++'s primary policy is that 0is an int, not a pointer.

Practically speaking, the same is true of NULL. There is some uncertainty in the details in NULL's case, because implementations are allowed to give NULLan integral type other than int(e.g., long). That's not common, but it doesn't really matter, because the issue here isn't the exact type of NULL, it's that neither 0nor NULLhas a pointer type.

In C++98, the primary implication of this was that overloading on pointer and integral types could lead to surprises. Passing 0or NULLto such overloads never called a pointer overload:

void f(int); // three overloads of f

void f(bool);

void f(void*);

f(0); // calls f(int), not f(void*)

f(NULL); // might not compile, but typically calls

// f(int). Never calls f(void*)

The uncertainty regarding the behavior of f(NULL)is a reflection of the leeway granted to implementations regarding the type of NULL. If NULLis defined to be, say, 0L(i.e., 0as a long), the call is ambiguous, because conversion from longto int, longto bool,and 0Lto void*are considered equally good. The interesting thing about that call is the contradiction between the apparent meaning of the source code (“I'm calling fwith NULL— the null pointer”) and its actual meaning (“I'm calling fwith some kind of integer — not the null pointer”). This counterintuitive behavior is what led to the guideline for C++98 programmers to avoid overloading on pointer and integral types. That guideline remains valid in C++11, because, the advice of this Item notwithstanding, it's likely that some developers will continue to use 0and NULL, even though nullptris a better choice.

nullptr's advantage is that it doesn't have an integral type. To be honest, it doesn't have a pointer type, either, but you can think of it as a pointer of all types. nullptr's actual type is std::nullptr_t, and, in a wonderfully circular definition, std::nullptr_tis defined to be the type of nullptr. The type std::nullptr_timplicitly converts to all raw pointer types, and that's what makes nullptract as if it were a pointer of all types.

Calling the overloaded function fwith nullptrcalls the void*overload (i.e., the pointer overload), because nullptrcan't be viewed as anything integral:

f(nullptr); // calls f(void*) overload

Using nullptrinstead of 0or NULLthus avoids overload resolution surprises, but that's not its only advantage. It can also improve code clarity, especially when autovariables are involved. For example, suppose you encounter this in a code base:

auto result = findRecord( /* arguments */ );

if ( result == 0) {

}

If you don't happen to know (or can't easily find out) what findRecordreturns, it may not be clear whether resultis a pointer type or an integral type. After all, 0(what resultis tested against) could go either way. If you see the following, on the other hand,

auto result = findRecord( /* arguments */ );

if ( result == nullptr) {

}

there's no ambiguity: resultmust be a pointer type.

nullptrshines especially brightly when templates enter the picture. Suppose you have some functions that should be called only when the appropriate mutex has been locked. Each function takes a different kind of pointer:

int f1(std::shared_ptr spw); // call these only when

double f2(std::unique_ptr upw); // the appropriate

bool f3(Widget* pw); // mutex is locked

Calling code that wants to pass null pointers could look like this:

std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3

using MuxGuard = // C++11 typedef; see Item 9

std::lock_guard;

{

MuxGuard g(f1m); // lock mutex for f1

auto result = f1( 0); // pass 0 as null ptr to f1

} // unlock mutex

{

MuxGuard g(f2m); // lock mutex for f2

auto result = f2( NULL); // pass NULL as null ptr to f2

} // unlock mutex

{

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

Интервал:

Закладка:

Сделать

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

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


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

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

x