Порядок инициализации в классе и список инициализации конструктора

Я хочу инициализировать группу членов в классе, чтобы сохранить исходный файл чище. Однако объекты принимают аргумент, который я получаю только через конструктор, и могут инициализироваться либо в списке инициализации конструктора, либо в конструкторе через присваивание. (Второй вариант, конечно, не сработает.) Это в основном сценарий:

В заголовке

class Foo
{

public:
Foo(Pointer * ptr);

private:

Pointer * ptr;
Member m1{ptr, "SomeText"};
Member m2{ptr, "SomeOtherText"};
}

В CPP

Foo::Foo(Pointer*ptr) :
ptr(ptr)
{
// ...
}

Теперь вопрос: говорит ли стандарт что-нибудь о порядке инициализации между ptr а также m1 / m2? Очевидно, этот код будет работать только тогда, когда ptrинициализируется раньше m1 а также m2,

3

Решение

Это гарантируется стандартом, что нестатические члены данных будут инициализированы в порядке их объявлений в определении класса. Как они инициализируются (с помощью инициализатора элемента по умолчанию или списка инициализаторов элемента) и порядок этих инициализаторов не имеет значения.

[Class.base.init] # 13.3

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

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

Это означает, что порядок инициализации всегда будет ptr -> m1 -> m2,

5

Другие решения

Порядок в определении класса важен и определяет порядок инициализации. Нет никакого способа избежать этого заказа, кроме как переопределить ваш класс (то есть поменять местами порядок).

Как только вы окажетесь внутри своего конструктора, вы можете назначать значение любой неконстантной переменной-члена с любым значением, которое вы хотите, но в этот момент они уже были инициализированы. Если вы хотите инициализировать член до этого, вы должны сделать это до тела конструктора — то есть использовать либо Foo::Foo(Pointer * ptr) : ptr(ptr) {} или инициализируя их, как вы делаете с m1 а также m2,

1

Это стандартно определяется. Члены инициализируются в порядке объявления внутри класса, поэтому Ваш код является абсолютно корректным. Потенциальная опасность — несогласованный порядок инициализации в конструкторе с порядком членов — тогда все еще поля инициализируются в порядке объявления.

0
По вопросам рекламы [email protected]