#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) {}
Это приводит к меньшей путанице в порядке инициализации, и две переменные больше не зависят друг от друга.