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

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

Интервал:

Закладка:

Сделать

With this information in mind, look again at this part of the original code:

bool highPriority = features(w)[5]; // declare highPriority's

// type explicitly

Here, featuresreturns a std::vectorobject, on which operator[]is invoked. operator[]returns a std::vector::referenceobject, which is then implicitly converted to the boolthat is needed to initialize highPriority. highPrioritythus ends up with the value of bit 5 in the std::vectorreturned by features, just like it's supposed to.

Contrast that with what happens in the auto-ized declaration for highPriority:

autohighPriority = features(w)[5]; // deduce highPriority's

// type

Again, featuresreturns a std::vectorobject, and, again, operator[]is invoked on it. operator[]continues to return a std::vector::referenceobject, but now there's a change, because autodeduces that as the type of highPriority. highPrioritydoesn't have the value of bit 5 of the std::vectorreturned by featuresat all.

The value it does have depends on how std::vector::referenceis implemented. One implementation is for such objects to contain a pointer to the machine word holding the referenced bit, plus the offset into that word for that bit. Consider what that means for the initialization of highPriority, assuming that such a std::vector::referenceimplementation is in place.

The call to featuresreturns a temporary std::vectorobject. This object has no name, but for purposes of this discussion, I'll call it temp . operator[]is invoked on temp , and the std::vector::referenceit returns contains a pointer to a word in the data structure holding the bits that are managed by temp , plus the offset into that word corresponding to bit 5. highPriorityis a copy of this std::vector::referenceobject, so highPriority, too, contains a pointer to a word in temp , plus the offset corresponding to bit 5. At the end of the statement, temp is destroyed, because it's a temporary object. Therefore, highPrioritycontains a dangling pointer, and that's the cause of the undefined behavior in the call to processWidget:

processWidget(w, highPriority); // undefined behavior!

// highPriority contains

// dangling pointer!

std::vector::referenceis an example of a proxy class : a class that exists for the purpose of emulating and augmenting the behavior of some other type. Proxy classes are employed for a variety of purposes. std::vector::referenceexists to offer the illusion that operator[]for std::vectorreturns a reference to a bit, for example, and the Standard Library's smart pointer types (see Chapter 4) are proxy classes that graft resource management onto raw pointers. The utility of proxy classes is well-established. In fact, the design pattern “Proxy” is one of the most longstanding members of the software design patterns Pantheon.

Some proxy classes are designed to be apparent to clients. That's the case for std::shared_ptrand std::unique_ptr, for example. Other proxy classes are designed to act more or less invisibly. std::vector::referenceis an example of such “invisible” proxies, as is its std::bitsetcompatriot, std::bitset::reference.

Also in that camp are some classes in C++ libraries employing a technique known as expression templates . Such libraries were originally developed to improve the efficiency of numeric code. Given a class Matrixand Matrixobjects m1, m2, m3, and m4, for example, the expression

Matrix sum = m1 + m2 + m3 + m4;

can be computed much more efficiently if operator+for Matrixobjects returns a proxy for the result instead of the result itself. That is, operator+for two Matrixobjects would return an object of a proxy class such as Suminstead of a Matrixobject. As was the case with std::vector::referenceand bool, there'd be an implicit conversion from the proxy class to Matrix, which would permit the initialization of sumfrom the proxy object produced by the expression on the right side of the “ =”. (The type of that object would traditionally encode the entire initialization expression, i.e., be something like Sum, Matrix>, Matrix>. That's definitely a type from which clients should be shielded.)

As a general rule, “invisible” proxy classes don't play well with auto. Objects of such classes are often not designed to live longer than a single statement, so creating variables of those types tends to violate fundamental library design assumptions. That's the case with std::vector::reference, and we've seen that violating that assumption can lead to undefined behavior.

You therefore want to avoid code of this form:

auto someVar = expression of "invisible" proxy class type ;

But how can you recognize when proxy objects are in use? The software employing them is unlikely to advertise their existence. They're supposed to be invisible , at least conceptually! And once you've found them, do you really have to abandon autoand the many advantages Item 5demonstrates for it?

Let's take the how-do-you-find-them question first. Although “invisible” proxy classes are designed to fly beneath programmer radar in day-to-day use, libraries using them often document that they do so. The more you've familiarized yourself with the basic design decisions of the libraries you use, the less likely you are to be blindsided by proxy usage within those libraries.

Where documentation comes up short, header files fill the gap. It's rarely possible for source code to fully cloak proxy objects. They're typically returned from functions that clients are expected to call, so function signatures usually reflect their existence. Here's the spec for std::vector::operator[], for example:

namespace std { // from C++ Standards

template

class vector {

public:

class reference{ … };

referenceoperator[](size_type n);

};

}

Assuming you know that operator[]for std::vectornormally returns a T&, the unconventional return type for operator[]in this case is a tip-off that a proxy class is in use. Paying careful attention to the interfaces you're using can often reveal the existence of proxy classes.

In practice, many developers discover the use of proxy classes only when they try to track down mystifying compilation problems or debug incorrect unit test results. Regardless of how you find them, once autohas been determined to be deducing the type of a proxy class instead of the type being proxied, the solution need not involve abandoning auto. autoitself isn't the problem. The problem is that autoisn't deducing the type you want it to deduce. The solution is to force a different type deduction. The way you do that is what I call the explicitly typed initializer idiom .

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

Интервал:

Закладка:

Сделать

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

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


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

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

x