Список инициализации членов C 20 Clang против G

#c #gcc #clang

Вопрос:

В настоящее время используется Clang 13.0.0 и GCC G 11.2.0.

Приведенный ниже код был упрощен для контекста. Когда я запускаю код с использованием g , он запускается без каких-либо предупреждений или ошибок. Когда я запускаю код с помощью Clang, я получаю следующую ошибку:

field 'cat' is uninitialized when used here [-Werror,-Wuninitialized]

Есть ли какой-нибудь способ решить эту проблему?

Код:

 struct Bar {  Object *ptr;  int y; };  struct Foo {  Object *ptr;  Bar cat; };  class Test {  Foo animal;   Test()  : animal{  generateObject(),  {  animal.ptr,  0   }  }  {} };  

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

1. cat{0, 0} 🙂

2. Что ж, cat{0, 0} это был бы очевидный способ решить эту проблему.

3. Но что, если бы мне понадобилось использовать cat.x? Пришлось бы мне использовать другой подход, чтобы избежать этой ситуации? Или это нормально, если он компилируется только с помощью g ?

4. @Locklan: Clang прав, так как это было бы UB. cat.x еще не инициализировано. gcc просто не замечает проблемы.

5. Зачем вам нужно использовать cat.x , особенно до того, как он был инициализирован?

Ответ №1:

Один из возможных подходов:

 class Test { private:  explicit Test(Object* ptr)  : animal{ptr, {ptr, 0}} {} public:  Test() : Test(generateObject()) {} };  

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

1. Могу я спросить, что делает ключевое слово explicit?

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