Скотт Мейерс - Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14
- Название:Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2016
- Город:Москва
- ISBN:978-5-8459-2000-3
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Мейерс - Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 краткое содержание
В книге рассматриваются следующие темы. Освоение С++11 и С++14 — это больше, чем просто ознакомление с вводимыми этими стандартами возможностями (например, объявлениями типов
, семантикой перемещения, лямбда-выражениями или поддержкой многопоточности). Вопрос в том, как использовать их эффективно, чтобы создаваемые программы были корректны, эффективны и переносимы, а также чтобы их легко можно было сопровождать. Именно этим вопросам и посвящена данная книга, описывающая создание по-настоящему хорошего программного обеспечения с использованием C++11 и С++14 — т.е. с использованием современного С++.
■ Преимущества и недостатки инициализации с помощью фигурных скобок, спецификации
, прямой передачи и функций
интеллектуальных указателей
■ Связь между
,
, rvalue-ссылками и универсальными ссылками
■ Методы написания понятных, корректных,
лямбда-выражений
■ Чем
отличается от
, как они используются и как соотносятся с API параллельных вычислений С++
■ Какие из лучших методов “старого” программирования на С++ (т.е. С++98) должны быть пересмотрены при работе с современным С++
Более чем 20 лет книги
серии
являются критерием уровня книг по программированию на С++. Понятное пояснение сложного технического материала принесло ему всемирную известность. Он всегда самый желанный гость на международных конференциях, а его услуги консультанта широко востребованы во всем мире.
Скотт Мейерс Эффективный и современный С++, После изучения основ С++ я перешел к изучению того, как применять С++ в промышленном программировании, с помощью серии книг Скотта Мейерса Эффективный С++. Эффективный и современный С++ — наиболее важная из книг серии, предлагающая ключевые рекомендации, стили и идиомы, позволяющие эффективно использовать современный С++. Вы еще не купили эту книгу? Сделайте это прямо сейчас. Герб Саттер,
глава Комитета ISO по стандартизации С++, специалист в области архитектуры программного обеспечения на С++ в Microsoft
Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
return static_cast>(enumerator);
}
Независимо от того, как он написан, шаблон toUType
позволяет нам обратиться к полю кортежа следующим образом:
auto val = std::get< toUType(UserInfoFields::uiEmail)>(uInfo);
Это все же больше, чем достаточно написать при использовании перечисления без области видимости, но зато позволяет избежать загрязнения пространства имен и непреднамеренных преобразований перечислителей. Во многих случаях вы можете решить, что набор нескольких дополнительных символов является разумной ценой за возможность избежать ловушек перечислений, появление которых восходит ко времени, когда вершиной достижений в цифровых телекоммуникациях был модем со скоростью 2400 бод.
• Перечисления в стиле С++98 в настоящее время известны как перечисления без областей видимости.
• Перечислители перечислений с областями видимости видимы только внутри перечислений. Они преобразуются в другие типы только с помощью явных приведений.
• Как перечисления с областями видимости, так и без таковых поддерживают указание базового типа. Базовым типом по умолчанию для перечисления с областью видимости является int
. Перечисление без области видимости базового типа по умолчанию не имеет.
• Перечисления с областями видимости могут быть предварительно объявлены. Перечисления без областей видимости могут быть предварительно объявлены, только если их объявление указывает базовый тип.
3.5. Предпочитайте удаленные функции закрытым неопределенным
Если вы предоставляете код другим разработчикам и хотите предотвратить вызов ими некоторой функции, обычно вы просто ее не объявляете. Нет объявления функции — нечего и вызывать. Но иногда С++ объявляет функции вместо вас, и если вы хотите предотвратить вызов таких функций клиентами вашего кода, придется постараться.
Эта ситуация возникает только для “специальных функций-членов”, т.e. функций-членов, которые при необходимости С++ генерирует автоматически. В разделе 3.11 эти функции рассматриваются более подробно, а пока что мы будем беспокоиться только о копирующем конструкторе и копирующем операторе присваивания. Эта глава во многом посвящена распространенным практикам С++98, для которых есть более эффективная замена в С++11, а в С++98, когда вы хотите подавить применение функции-члена, это почти всегда копирующий конструктор, оператор присваивания или они оба.
Подход С++98 для предотвращения применения этих функций состоит в объявлении их как private
без предоставления определений. Например, вблизи с основанием иерархии потоков ввода-вывода в стандартной библиотеке С++ находится шаблонный класс basic_ios
. Все классы потоков наследуют (возможно, косвенно) этот класс. Копирование потоков ввода-вывода нежелательно, поскольку не совсем очевидно, что же должна делать такая операция. Объект istream,
например, представляет поток входных значений, одни из которых могут уже быть считаны, а другие могут потенциально быть считаны позже. Если копировать такой поток, то должно ли это повлечь копирование всех считанных значений, а также значений, которые будут считаны в будущем? Простейший способ разобраться в таких вопросах — объявить их несуществующими. Именно это делает запрет на копирование потоков.
Чтобы сделать классы потоков некопируемыми, basic_ios
в С++98 объявлен следующим образом (включая комментарии):
template >
class basic_ios : public ios_base {
public:
…
private:
basic_ios(const basic_ios&); // Не определен
basic_ios& operator=(const basic_ios&); // Не определен
};
Объявление этих функций как private предотвращает их вызов клиентами. Умышленное отсутствие их определений означает, что если код, все еще имеющий к ним доступ (т.e. функции-члены или друзья класса), ими воспользуется, то компоновка (редактирование связей) будет неудачной из-за отсутствия определений функций.
В С++11 имеется лучший способ достичь по сути того же самого: воспользоваться конструкцией “ = delete
”: чтобы пометить копирующий конструктор и копирующее присваивание как удаленные функции . Вот та же часть basic_ios
в С++11:
template >
class basic_ios : public ios_base {
public:
…
basic_ios(const basic_ios& ) = delete;
basic_ios& operator=(const basic_ios&) = delete;
};
Отличие удаления этих функций от их объявления как private
может показаться больше вопросом вкуса, чем чем-то иным, но на самом деле в это заложено больше, чем вы думаете. Удаленные функции не могут использоваться никоим образом, так что даже код функции- члена или функций, объявленных как friend
, не будет компилироваться, если попытается копировать объекты basic_ios
. Это существенное улучшение по сравнению с поведением С++98, где такое некорректное применение функций не диагностируется до компоновки.
По соглашению удаленные функции объявляются как public
, а не private
. Тому есть причина. Когда код клиента пытается использовать функцию-член, С++ проверяет доступность до проверки состояния удаленности. Когда клиентский код пытается использовать функцию, объявленную как private
, некоторые компиляторы жалуются на то, что это закрытая функция, несмотря на то что доступность функции никак не влияет на возможность ее использования. Стоит принять это во внимание при пересмотре старого кода и замене не определенных функций-членов, объявленных как private
, удаленными, поскольку объявление удаленных функций как public в общем случае приводит к более корректным сообщениям об ошибках.
Важным преимуществом удаленных функций является то, что удаленной может быть любая функция, в то время как быть private
могут только функции-члены. Предположим, например, что у нас есть функция, не являющаяся членом, которая принимает целочисленное значение и сообщает, является ли оно “счастливым числом”:
bool isLucky(int number);
То, что С++ является наследником С, означает, что почти любой тип, который можно рассматривать как отчасти целочисленный, будет неявно преобразовываться в int
, но некоторые компилируемые вызовы могут не иметь смысла:
if (isLucky('a')) … // Является ли 'a' счастливым числом?
if (isLucky(true)) … // Является ли true счастливым числом?
if (isLucky(3.5)) … // Следует ли выполнить усечение до 3
// перед проверкой на "счастливость"?
Если счастливые числа действительно должны быть только целыми числами, хотелось бы предотвратить такие вызовы, как показано выше.
Один из способов достичь этого — создание удаленных перегрузок для типов, которые мы хотим отфильтровывать:
Читать дальшеИнтервал:
Закладка: