C ++ конструктор по умолчанию и вопросы POD при инициализации нового объекта - PullRequest
3 голосов
/ 21 мая 2019

Я понимаю разницу (по крайней мере, мне кажется, что я понимаю) разницу между конструктором по умолчанию и предоставленным пользователем пустым конструктором и тем, что означает POD. Однако есть некоторые варианты поведения, которые я не совсем понимаю во время инициализации объекта:

#include <iostream>
using namespace std;
//POD
struct A {
    int a, b, c;
};

//Not POD
struct B {
    B() {};
    int a, b, c;
};

int main(){

A a = {1,2,3} \\ Case 1. Works, this is how we initialize a POD type
B b1 = {1,2,3} \\ Case 2. Doesn't work, since B is not POD
B b2;          \\ Case 3. Works, call the user provided empty constructor but a, b and c are not initialized
A c{};        \\ Case 4. Works, initialize everything to 0
A d;          \\ Case 5. Doesn't work. This is the case I don't understand
cout << a.a << a.b << a.c << endl;
cout << b1.a << b1.b << b1.c << endl;
cout << b2.a << b2.b << b2.c << endl;
cout << c.a << c.b << c.c << endl;
cout << d.a << d.b << d.c << endl;
}

Как упоминалось выше, случай 5 - это поведение, которое я не понимаю. Я ожидал, что он вызовет конструктор по умолчанию и инициализирует каждый член равным 0. Однако я получаю ошибку компиляции:

Ошибка C4700, использованная неинициализированная локальная переменная 'd'

Может кто-нибудь помочь мне понять, почему он сообщает об ошибке выше? Я работаю в Windows и использую компилятор Visual Studio.

Ответы [ 2 ]

2 голосов
/ 21 мая 2019

Отвечая на другой аспект вопроса, а именно ' PODness '.

POD - это устаревшее определение, и оно больше не используется, так как не может охватывать разнообразиеситуаций.Это устарело в C ++ 20.Вместо этого используются различные термины для обсуждения совместимости классов со структурами Си (потому что, в конце концов, это все, о чем идет речь).

В частности, наиболее важные свойства (по крайней мере, на мой взгляд):

  • Стандартная компоновка : это важно, потому что, с точки зрения непрофессионалов, когда класс является стандартной компоновкой, объект может обрабатываться как последовательность байтов, отправляемых в какую-либо другую программу(потенциально написанные на другом языке) и восстановленные из этой последовательности на принимающей стороне (после учета заполнения).Это играет большую роль, когда сериализованные данные объекта отправляются по сети или сохраняются в файлы
  • Тривиально копируемое : это важно, потому что, когда класс тривиально копируем, один объект может быть создан издругой - просто копирование байтов памяти из одного объекта.Это играет большую роль в оптимизации
  • Тривиальный тип , расширение тривиально копируемого требования сверху: это важно, потому что, когда класс является тривиальным типом, любая случайная последовательность байтов может рассматриваться какдопустимый объект типа (после учета псевдонимов памяти).
0 голосов
/ 21 мая 2019
Error C4700 uninitialized local variable 'd' used

Может кто-нибудь помочь мне понять, почему он сообщает об ошибке выше?

Ошибка означает, что вы (вероятно?) Прочитали неопределенное значение. Поведение чтения неопределенного значения не определено (не принимая во внимание определенное исключение, которое, очевидно, не применимо в вашем случае).

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

Технически, чтение неопределенного значения не делает программу плохо сформированной, поэтому запрещается компиляция. Вполне возможно, что вы настроили свой компилятор на намеренное нарушение стандарта, отказавшись от компиляции в случае предупреждения. Если нет, то это может быть ошибкой соответствия в компиляторе.

Решение: не читать неопределенные значения. Вы можете присвоить инициализации значение ноль или перечислить инициализацию для других значений. См., Например, случаи 1 и 4.


Незначительные исправления о номенклатуре:

Случай 3. Работает, вызывать предоставленный пользователем пустой конструктор, но a, b и c инициализируются случайными значениями мусора

Точнее: элементы не инициализированы, и потенциально 1 остаются с неопределенными значениями.

1 В вашем примере вы объявляете переменные со статическим хранилищем. Они изначально инициализируются нулями перед динамической инициализацией. Таким образом, в вашем примере члены не имеют неопределенных значений, а обнуляются.

Случай 4. Работает, инициализировать все до 0, вызывая конструктор по умолчанию

int s не имеют «конструкторов по умолчанию». Они являются инициализированными значениями. Значение инициализации int равно нулю инициализации.

...