C Является ли плохой идеей инициализировать членов класса, назначая им других инициализированных конструктором членов класса?

#c #class #initialization #class-members

Вопрос:

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

 class test{
public:
    test(int c) : i(c) {
    }

    int i;
    int q = i;
};

int main() {
    std::cout << test(1).q << std::endl; //outputs 1
}
 

Однако, если я поменяю порядок объявления i и q :

 int q = i;
int i;
 

i Вывод на печать выходов 0.

Это плохая идея-инициализировать членов класса таким образом? Очевидно, что в этом примере, вероятно, проще просто добавить : i(c), q(c) в конструктор.

Но для ситуаций, когда есть член класса, который полагается i , например, на какой-либо объект с конструктором, который принимает int ( i ) и имеет частный = оператор и конструктор копирования, может ли этот подход быть хорошим способом инициализации этого объекта? Или это плохая идея, и ее всегда следует избегать?

Комментарии:

1. Элементы инициализируются в том порядке, в котором они определены. Даже если вы : q(c), i(c) находитесь в списке инициализаторов участников, если i он определен первым, i он будет инициализирован первым. Никаких исключений. Они также будут уничтожены в обратном порядке, без исключений, так что у вас есть надежные гарантии поведения.

2. Да, это плохая идея. Как вы уже видели, все, что нужно, — это чтобы кто-то изменил порядок переменных, и теперь код не работает.

3. Технически на это можно положиться int i; int q = i; , но, как вы показали, оно может легко сломаться. Я бы рекомендовал этого не делать, но в конечном счете это, вероятно, вопрос мнения.

4. Для случая (2) увеличьте уровень предупреждения компилятора — live — godbolt.org/z/e6Mv1hhTz

Ответ №1:

Да, вы обрисовали условия неудачи. Нетрудно представить, что кто-то непреднамеренно взломал ваш код из-за изменения порядка.

Если вы хотели сделать что-то подобное, лучше всего назначить оба в конструкторе из источника ввода.

 test(int c) : q(c), i(c) {}
 

Это приводит к меньшей путанице в порядке инициализации, и две переменные больше не зависят друг от друга.