15 Special member functions [special]

15.6 Initialization [class.init]

15.6.2 Initializing bases and members [class.base.init]

В определении конструктора для класса инициализаторы для прямых и виртуальных подобъектов базового класса и нестатических членов данных могут быть указаны с помощью a ctor-initializer, который имеет форму

ctor-initializer:
	: mem-initializer-list
mem-initializer-list:
	mem-initializer ...opt
	mem-initializer-list , mem-initializer ...opt
mem-initializer:
	mem-initializer-id ( expression-listopt )
	mem-initializer-id braced-init-list
mem-initializer-id:
	class-or-decltype
	identifier

В mem-initializer-idисходном неквалифицированном поиске identifierвыполняется поиск в области действия класса конструктора, и, если он не найден в этой области, выполняется поиск в области, содержащей определение конструктора. [ Note: Если класс конструктора содержит член с тем же именем, что и прямой или виртуальный базовый класс класса, mem-initializer-id именование члена или базового класса, состоящее из одного идентификатора, относится к члену класса. Для mem-initializer-id скрытого базового класса можно указать полное имя. ] Если не названы класс конструктора, нестатический член данных класса конструктора или прямая или виртуальная база этого класса, объект имеет неправильный формат.end notemem-initializer-idmem-initializer

A mem-initializer-list может инициализировать базовый класс, используя любой, class-or-decltypeкоторый обозначает этот тип базового класса. [Example:

struct A { A(); };
typedef A global_A;
struct B { };
struct C: public A, public B { C(); };
C::C(): global_A() { }          // mem-initializer for base A

end example]

Если a mem-initializer-id неоднозначно, потому что он обозначает как прямой не виртуальный базовый класс, так и унаследованный виртуальный базовый класс, mem-initializer это неправильно сформировано. [Example:

struct A { A(); };
struct B: public virtual A { };
struct C: public A, public B { C(); };
C::C(): A() { }                 // ill-formed: which A?

end example]

A ctor-initializer может инициализировать вариантный член класса конструктора. Если a ctor-initializer указывает более одного mem-initializer для одного и того же члена или для одного и того же базового класса, ctor-initializer это неправильно сформировано.

A mem-initializer-listможет делегировать другому конструктору класса конструктора, используя любой, class-or-decltypeкоторый обозначает сам класс конструктора. Если mem-initializer-idобозначает класс конструктора, он должен быть единственным mem-initializer; конструктор - этоdelegating constructor, а конструктор, выбранный объектом, mem-initializer- этоtarget constructor. Целевой конструктор выбирается по разрешению перегрузки. После возврата целевого конструктора выполняется тело делегирующего конструктора. Если конструктор прямо или косвенно делегирует себе полномочия, программа имеет неправильный формат и диагностика не требуется. [Example:

struct C {
  C( int ) { }                  // #1: non-delegating constructor
  C(): C(42) { }                // #2: delegates to #1
  C( char c ) : C(42.0) { }     // #3: ill-formed due to recursion with #4
  C( double d ) : C('a') { }    // #4: ill-formed due to recursion with #3
};

end example]

expression-list Или braced-init-list в mem-initializer используются для инициализации назначенного субобъекта (или, в случае делегирования конструктора, полный класс объекта) в соответствии с правилами инициализаций[dcl.init] для прямой инициализации. [Example:

struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
  D(int);
  B1 b;
  const int c;
};

D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ }
D d(10);

end example] [ Note: Инициализация, выполняемая каждым из них, mem-initializer представляет собой файлfull-expression. Любое выражение в a mem-initializer оценивается как часть полного выражения, выполняющего инициализацию. ] A, где означает, что виртуальный базовый класс игнорируется во время выполнения конструктора любого класса, который не является самым производным классом.end notemem-initializermem-initializer-id

Временное выражение, привязанное к ссылочному элементу в a, mem-initializer имеет неправильный формат. [Example:

struct A {
  A() : v(42) { }   // error
  const int& v;
};

end example]

В конструкторе без делегирования, если данный потенциально сконструированный подобъект не обозначен a mem-initializer-id (включая случай, когда его нет, mem-initializer-list потому что у конструктора нет ctor-initializer), тогда

  • если объект является нестатическим членом данных, который имеетdefault member initializer либо

    • класс конструктора - этоunion, и никакой другой вариантный член этого союза не обозначен символом mem-initializer-idили

    • класс конструктора не является объединением, и, если предприятие является членом анонимного союза, ни один из членов этого союза не обозначаются mem-initializer-id,

    сущность инициализируется из инициализатора члена по умолчанию, как указано в[dcl.init];

  • в противном случае, если сущность является анонимным объединением или вариантом member ([class.union.anon]), инициализация не выполняется;

  • в противном случае - сущностьdefault-initialized.

[ Note: Anabstract class никогда не является наиболее производным классом, поэтому его конструкторы никогда не инициализируют виртуальные базовые классы, поэтому соответствующий класс mem-initializers может быть опущен. ] Попытка инициализировать более одного нестатического элемента данных объединения приводит к неправильному формату программы. [ После того , как вызов конструктора для класса для объекта с автоматической или динамической продолжительностью хранения завершен, если конструктор не был вызван как часть значения инициализации и член не является ни инициализацией , ни присваивается значение во время выполнения из тело конструктора, член имеет неопределенное значение. ] [end noteNote: XXcompound-statementend noteExample:

struct A {
  A();
};

struct B {
  B(int);
};

struct C {
  C() { }               // initializes members as follows:
  A a;                  // OK: calls A​::​A()
  const B b;            // error: B has no default constructor
  int i;                // OK: i has indeterminate value
  int j = 5;            // OK: j has the value 5
};

end example]

Если данный нестатический член данных имеет как инициализатор члена по умолчанию, так и a mem-initializer, выполняется инициализация, указанная в mem-initializer, и инициализатор члена нестатических данных по умолчанию игнорируется. [ Example: Учитывая

struct A {
  int i = /* some integer expression with side effects */ ;
  A(int arg) : i(arg) { }
  // ...
};

A(int) конструктор просто инициализацииi со значением arg, и побочных эффектов вiинициализаторе члена по умолчанию «S не будет иметь место. ]end example

Временное выражение, привязанное к ссылочному элементу из инициализатора элемента по умолчанию, имеет неправильный формат. [Example:

struct A {
  A() = default;        // OK
  A(int v) : v(v) { }   // OK
  const int& v = 42;    // OK
};
A a1;                   // error: ill-formed binding of temporary to reference
A a2(1);                // OK, unfortunately

end example]

В конструкторе без делегирования деструктором для каждого потенциально сконструированного подобъекта типа класса являетсяpotentially invoked. [ Note: Это положение гарантирует, что деструкторы могут быть вызваны для полностью сконструированных подобъектов в случае возникновения исключения ([except.ctor]). ]end note

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

  • Во-первых, и только для конструктораmost derived classвиртуальных базовых классов инициализируются в том порядке, в котором они появляются при обходе направленного ациклического графа базовых классов в глубину слева направо, где «слева направо» порядок появления базовых классов в производном классе base-specifier-list.

  • Затем прямые базовые классы инициализируются в порядке объявления, как они появляются в base-specifier-list (независимо от порядка mem-initializers).

  • Затем нестатические элементы данных инициализируются в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка mem-initializers).

  • Наконец, compound-statementвыполняется тело конструктора.

[ Note: Порядок объявления необходим, чтобы гарантировать, что базовые и членские подобъекты уничтожаются в порядке, обратном инициализации. ]end note

[Example:

struct V {
  V();
  V(int);
};

struct A : virtual V {
  A();
  A(int);
};

struct B : virtual V {
  B();
  B(int);
};

struct C : A, B, virtual V {
  C();
  C(int);
};

A::A(int i) : V(i) { /* ... */ }
B::B(int i) { /* ... */ }
C::C(int i) { /* ... */ }

V v(1);             // use V(int)
A a(2);             // use V(int)
B b(3);             // use V()
C c(4);             // use V()

end example]

Имена в expression-list или braced-init-list из a mem-initializer оцениваются в области действия конструктора, для которого mem-initializer указан. [Example:

class X {
  int a;
  int b;
  int i;
  int j;
public:
  const int& r;
  X(int i): r(a), b(i), i(i), j(this->i) { }
};

инициализируется X​::​r для ссылки X​::​a, инициализируется X​::​b значением параметра конструктора i, инициализируется X​::​i значением параметра конструктора iи инициализируется X​::​j значением X​::​i; это происходит каждый раз, когда создается объект класса X . ] [ Поскольку они оцениваются в области видимости конструктора, указатель может использоваться в элементе a для ссылки на инициализируемый объект. ]end exampleNote: mem-initializerthisexpression-listmem-initializerend note

Дляvirtual member functionsстроящегося объекта можно вызывать функции-члены (в том числе ). Точно так же строящийся объект может быть операндом typeid operator или для dynamic_­cast. Однако, если эти операции выполняются в ctor-initializer (или в функции, вызываемой прямо или косвенно из a ctor-initializer) до завершения всех mem-initializers базовых классов for, программа имеет неопределенное поведение. [Example:

class A {
public:
  A(int);
};

class B : public A {
  int j;
public:
  int f();
  B() : A(f()),     // undefined: calls member function but base A not yet initialized
  j(f()) { }        // well-defined: bases are all initialized
};

class C {
public:
  C(int);
};

class D : public B, C {
  int i;
public:
  D() : C(f()),     // undefined: calls member function but base C not yet initialized
  i(f()) { }        // well-defined: bases are all initialized
};

end example]

[ Note: [class.cdtor] описывает результат вызовов виртуальных функций typeid и dynamic_­casts во время построения для четко определенных случаев; то есть описывает polymorphic behavior строящийся объект. ]end note

За mem-initializerкоторым следует многоточиеpack expansion , инициализируются базовые классы, указанные в раскрытии пакета в base-specifier-list классе. [Example:

template<class... Mixins>
class X : public Mixins... {
public:
  X(const Mixins&... mixins) : Mixins(mixins)... { }
};

end example]