Читаем Параллельное программирование на С++ в действии полностью

• Классы с тривиальными конструктором по умолчанию, копирующим конструктором, копирующим оператором присваивания и деструктором можно использовать в объединении (union), в котором определены пользовательские конструктор и деструктор.

• Классы с тривиальными конструктором копирующим оператором присваивания можно использовать вместе с шаблонным классом std::atomic<> (см. раздел 5.2.6), то есть передавать значения такого типа атомарным операциям.

Одного объявления функции со спецификатором = default недостаточно, чтобы сделать ее тривиальной, для этого класс должен удовлетворять всем прочим условиям, при которых соответствующая функция будет тривиальной. Однако явно написанная пользователем функция не будет тривиальной никогда.

Второе различие между классами с функциями, сгенерированными компилятором и написанными пользователем, заключается в том, что класс без написанных пользователем конструкторов может быть агрегатным и, стало быть, допускать инициализацию с помощью агрегатного инициализатора:

struct aggregate {

 aggregate() = default;

 aggregate(aggregate const&) = default;

 int a;

 double b;

};

aggregate x={42, 3.141};

В данном случае x.a инициализируется значением 42, a x.b — значением 3.141.

Третье различие малоизвестно и относится только к конструктору по умолчанию, да и то лишь в классах, удовлетворяющих определенному условию. Рассмотрим такой класс:

struct X {

 int а;

};

Если экземпляр класса X создается без инициализатора, то содержащееся в нем значение (а) типа int инициализируется по умолчанию. Если у объекта статический класс памяти, то значение инициализируется нулем, в противном случае начальное значение произвольно, что может привести к неопределённому поведению, если программа обращается к объекту раньше, чем ему будет присвоено значение:

X x1; ←значение x1.a не определено

С другой стороны, если инициализировать экземпляр X путем явного вызова конструктора по умолчанию, то он получит значение 0:

X x2 = X(); ←x2.а == 0

Это странное свойство распространяется также на базовые классы и члены классов. Если в классе имеется сгенерированный компилятором конструктор по умолчанию, и каждый член самого класса и всех его базовых классов также имеет сгенерированный компилятором конструктор по умолчанию, то переменные-члены самого класса и его базовых классов, принадлежащие встроенным типам, также будут иметь неопределенное значение или будут инициализированы нулями в зависимости от того, вызывался ли явно для внешнего класса его конструктор по умолчанию.

У этого замысловатого и потенциально чреватого ошибками правила есть тем не менее применения, а, если вы пишете конструктор по умолчанию самостоятельно, то это свойство утрачивается; данные-члены (например, а) либо всегда инициализируются (коль скоро вы указали значение или явно вызвали конструктор по умолчанию), либо вообще не инициализируются (если вы этого не сделали):

X::X() : а() {}   ←всегда а == 0

X::X() : а(42) {} ←всегда а == 42

X::X() {}         ←(1)

Если инициализация а при конструировании X не производится (как в третьем примере (1)), то a остается неинициализированным для нестатических экземпляров X и инициализируется нулем для экземпляров X со статическим временем жизни.

Обычно, если вы вручную напишете хотя бы один конструктор, то компилятор не станет генерировать конструктор по умолчанию. Стало быть, если он вам все-таки нужен, его придётся написать самостоятельно, а тогда это странное свойство инициализации теряется. Однако явно объявив конструктор умалчиваемым, вы можете заставить компилятор сгенерировать конструктор по умолчанию и сохранить это свойство:

X::X() = default;

Это свойство используется в атомарных типах (см. раздел 5.2), в которых конструктор по умолчанию явно объявлен умалчиваемым. У таких типов начальное значение не определено, если только не выполняется одно из следующих условий: (а) задан статический класс памяти (тогда значение инициализируется нулем); (b) для инициализации нулем явно вызван конструктор по умолчанию; (с) вы сами явно указали начальное значение. Отметим, что в атомарных типах конструктор для инициализации значением объявлен как constexpr (см. раздел А.4), чтобы разрешить статическую инициализацию.

<p>А.4. <code>constexpr</code>-функции</p>

Целые литералы, например 42, — это константные выражения. Равно как и простые арифметические выражения, например 23*2-4. Частью константного выражения могут быть также const-переменные любого целочисленного типа, которые сами инициализированы константным выражением:

const int i = 23;

const int two_i = i * 2;

const int four = 4;

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных