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

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

Интервал:

Закладка:

Сделать

};

This won't compile, of course, because when written this way, compilers will kvetch about all the overriding-related problems. That's exactly what you want, and it's why you should declare all your overriding functions override.

The code using overridethat does compile looks as follows (assuming that the goal is for all functions in Derivedto override virtuals in Base):

class Base {

public:

virtual void mf1() const;

virtual void mf2(int x);

virtual void mf3() &

virtualvoid mf4() const;

};

class Derived: public Base {

public:

virtual void mf1() constoverride;

virtual void mf2( intx) override;

virtual void mf3() &override;

void mf4() const override; // adding "virtual" is OK,

}; // but not necessary

Note that in this example, part of getting things to work involves declaring mf4virtual in Base. Most overriding-related errors occur in derived classes, but it's possible for things to be incorrect in base classes, too.

A policy of using overrideon all your derived class overrides can do more than just enable compilers to tell you when would-be overrides aren't overriding anything. It can also help you gauge the ramifications if you're contemplating changing the signature of a virtual function in a base class. If derived classes use overrideeverywhere, you can just change the signature, recompile your system, see how much damage you've caused (i.e., how many derived classes fail to compile), then decide whether the signature change is worth the trouble. Without override, you'd have to hope you have comprehensive unit tests in place, because, as we've seen, derived class virtuals that are supposed to override base class functions, but don't, need not elicit compiler diagnostics.

C++ has always had keywords, but C++11 introduces two contextual keywords , overrideand final. [2] Applying final to a virtual function prevents the function from being overridden in derived classes. final may also be applied to a class, in which case the class is prohibited from being used as a base class. These keywords have the characteristic that they are reserved, but only in certain contexts. In the case of override, it has a reserved meaning only when it occurs at the end of a member function declaration. That means that if you have legacy code that already uses the name override, you don't need to change it for C++11:

class Warning { // potential legacy class from C++98

public:

void override(); // legal in both C++98 and C++11

… // (with the same meaning)

};

That's all there is to say about override, but it's not all there is to say about member function reference qualifiers. I promised I'd provide more information on them later, and now it's later.

If we want to write a function that accepts only lvalue arguments, we declare a non- constlvalue reference parameter:

void doSomething(Widget &w); // accepts only lvalue Widgets

If we want to write a function that accepts only rvalue arguments, we declare an rvalue reference parameter:

void doSomething(Widget &&w); // accepts only rvalue Widgets

Member function reference qualifiers simply make it possible to draw the same distinction for the object on which a member function is invoked, i.e., *this. It's precisely analogous to the constat the end of a member function declaration, which indicates that the object on which the member function is invoked (i.e., *this) is const.

The need for reference-qualified member functions is not common, but it can arise. For example, suppose our Widgetclass has a std::vector data member, and we offer an accessor function that gives clients direct access to it:

class Widget {

public:

using DataType = std::vector; // see Item 9 for

… // info on "using"

DataType& data() { return values; }

private:

DataType values;

};

This is hardly the most encapsulated design that's seen the light of day, but set that aside and consider what happens in this client code:

Widget w;

auto vals1 = w.data(); // copy w.values into vals1

The return type of Widget::datais an lvalue reference (a std::vector&, to be precise), and because lvalue references are defined to be lvalues, we're initializing vals1from an lvalue. vals1is thus copy constructed from w.values, just as the comment says.

Now suppose we have a factory function that creates Widgets,

Widget makeWidget();

and we want to initialize a variable with the std::vectorinside the Widgetreturned from makeWidget:

auto vals2 = makeWidget().data(); // copy values inside the

// Widget into vals2

Again, Widgets::datareturns an lvalue reference, and, again, the lvalue reference is an lvalue, so, again, our new object ( vals2) is copy constructed from valuesinside the Widget. This time, though, the Widgetis the temporary object returned from makeWidget(i.e., an rvalue), so copying the std::vectorinside it is a waste of time. It'd be preferable to move it, but, because datais returning an lvalue reference, the rules of C++ require that compilers generate code for a copy. (There's some wiggle room for optimization through what is known as the “as if rule,” but you'd be foolish to rely on your compilers finding a way to take advantage of it.)

What's needed is a way to specify that when datais invoked on an rvalue Widget, the result should also be an rvalue. Using reference qualifiers to overload datafor lvalue and rvalue Widgets makes that possible:

class Widget {

public:

using DataType = std::vector;

DataType& data() & // for lvalue Widgets,

{ return values; } // return lvalue

DataType data() && // for rvalue Widgets,

{ return std::move(values); } // return rvalue

private:

DataType values;

};

Notice the differing return types from the dataoverloads. The lvalue reference overload returns an lvalue reference (i.e., an lvalue), and the rvalue reference overload returns a temporary object (i.e., an rvalue). This means that client code now behaves as we'd like:

auto vals1 = w.data(); // calls lvalue overload for

// Widget::data, copy-

// constructs vals1

auto vals2 = makeWidget().data(); // calls rvalue overload for

// Widget::data, move-

// constructs vals2

This is certainly nice, but don't let the warm glow of this happy ending distract you from the true point of this Item. That point is that whenever you declare a function in a derived class that's meant to override a virtual function in a base class, be sure to declare that function override.

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

Интервал:

Закладка:

Сделать

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

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


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

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

x