Стабильно ли использовать арифметику в списке инициализации ctor? - PullRequest
7 голосов
/ 19 ноября 2011

Стабильно ли использовать что-то подобное в списке инициализации ctor класса во время неявного присваивания (никакие операторы не перегружены):

class C{
   public:
      C(int _var): var(_var), i(var*var) 
        {} 
   private:
      int var;
      int i;
};

Я получаю некоторые непредсказуемые результаты, почему это так?

Ответы [ 3 ]

8 голосов
/ 19 ноября 2011

Да.

Возможно, вы захотите избавиться от зависимости порядка инициализации и напишите:

  C(int _var): var(_var), i(_var*_var) 

По сути, заставляя меня зависеть от var, вы должны убедиться, что var объявлен до того, как я в классе.

Аналогично, вы можете инициализировать что-то в C, которое определено (и инициализировано) в родительском классе, потому что родительский элемент будет создан до C.

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

5 голосов
/ 19 ноября 2011

Да, это безопасно, но в этом случае вы должны быть осторожны. Вы используете var, а не _var, поэтому вы должны быть уверены, что var создан до i. Это тот случай, так как элементы построены в порядке их объявления (в данном случае var, i), что может отличаться от порядка их появления в списке инициализатора.

Так что в этом случае это работает. Это также будет работать в этом случае:

C(int _var):  i(var*var), var(_var)

но не в этом:

class C{
   public:
      C(int _var): var(_var), i(var*var) 
        {} 
   private:
      int i;
      int var;
};

Но, конечно, чтобы всегда быть в безопасности, вы можете просто использовать _var:

C(int _var):  var(_var), i(_var*_var)
5 голосов
/ 19 ноября 2011

Этот код имеет определенное значение, при условии, что умножение не переполняется.

Имейте в виду, что оно критически зависит от того факта, что var определено до i в классе (порядок в инициализаторесписок не имеет значения, все, что имеет значение, это порядок, в котором определяются сами члены).В противном случае i будет инициализирован с использованием элемента данных var.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...