C ++ правильный способ встроенной инициализации переменных-членов - PullRequest
3 голосов
/ 23 мая 2019

Учитывая пример кода:

struct S {
    char data[5];
    int a;
};

При запуске «Выполнить анализ кода» в Microsoft Visual Studio, он предупреждает об инициализации всех переменных.

Теперь я знаю, что вы можете сделать этоЕсть несколько способов создать конструктор по умолчанию, например:

S() :
    data{0},
    a{0} {
}

, который уберет предупреждение.Но что, если вы не хотите вручную создавать конструктор по умолчанию.

что-то вроде:

struct S {
    char data[5];
    int a = 0;
};

избавляется от предупреждения для a, но не data, хотя выможно исправить это, добавив {} после примерно так: char data[5]{}; это, кажется, делает анализ кода счастливым.

Это заставило меня задуматься, вы также можете инициализировать a как int a{0};

Итак, мой вопрос: все ли они действительны и какие предпочтительнее?

Примечание: я заметил, что std::array имеет _Ty _Elems[_Size];, который никогда нигде не инициализируется, и не имеет {} после негоЯ полагаю, они просто игнорируют это предупреждение?Или они делают что-то, что я не замечаю, чтобы «исправить» предупреждение?

Также хотел добавить, что этот код: #include #include

template<class T, std::size_t N>
struct static_vector {
    typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N] = {0};

    T& operator[](std::size_t pos)  {
        return *std::launder(reinterpret_cast<T*>(&data[pos]));
    }
};

int main(int argc, char**) {
    static_vector<int, 10> s;
    s[0] = argc;
    return s[0];
}

в gcc9.1 -std=c++17 -Wall не выдаетпредупреждения, но тот же код под clang8.0 -std=c++17 -Wall дает мне:

warning: suggest braces around initialization of subobject [-Wmissing-braces]
        typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N] = {0};
                                                                              ^
                                                                              {}

Я вижу, что могу установить его на = {};, который исправляет это, просто удивляясь, почему один компилятор выдаст предупреждение, когда другой«т?Какой из них по спецификации?

Ответы [ 2 ]

3 голосов
/ 23 мая 2019

В C ++ для каждого декларатора инициализатор может быть одним из следующих:

1. ( expression-list )
2. = expression 
3. { initializer-list }

Ниже приведено их описание:

  1. список произвольно разделенных запятымивыражения и фигурные скобки-init-списки в скобках
  2. знак равенства, за которым следует выражение
  3. фигурный-инициализированный список: возможно, пустой, разделенный запятыми список выражений и другие фигурные скобки-init-списки

Какой тип инициализации предпочитать, зависит от контекста.Чтобы инициализировать элементы данных в классе, я лично предпочитаю при инициализации класса с использованием braced initializer, так как в этом случае нам не нужно писать определяемый пользователем default constructor, сгенерированный компилятором один всегдаэффективные .

члены класса

Нестатические элементы данных можно инициализировать с помощью списка инициализаторов элементов или с помощью инициализатор элемента по умолчанию .

В вашем случае вы, вероятно, можете использовать:

struct S {
    char data[5] = {0}; //initialize by zero
    int a = 0;
};

или также дать им различные значения:

struct S {
    char data[5] = {0,1,2,3,4};
    int a = 0;
};

Подробнее см. Инициализация

1 голос
/ 23 мая 2019

Указание от CPPCoreGuidelines в следующих состояниях: Не определяйте конструктор по умолчанию, который только инициализирует элементы данных;вместо этого используйте инициализаторы членов класса

Так что вы можете просто сделать:

struct S {
    char data[5] = {0};
    int a = 0;
};

Что касается вашего другого вопроса об отсутствии предупреждения, связанного с std::array, GCC имеетобратите внимание, в котором говорится:

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

Я полагаю, что это также относится и к MSVC.

...