C++ Zero-Initialization

У меня возникают проблемы с пониманием, когда и почему именно член в моем классе инициализируется нулями в соответствии с http://en.cppreference.com/w/cpp/language/zero_initialization.

Рассмотрим следующую тестовую программу:

#include <iostream>
#include <stdio.h>

class MyTest {
private:
    const static unsigned int dimension = 8;
    void (* myFunctions [dimension])();

public: 
    MyTest() {}

    void print() { 
        for(unsigned int i=0; i < MyTest::dimension; i++) {
            printf("myFunctions[%d] = %p\n", i, this->myFunctions[i]);
        }   
    }
};


int main() {
    //We declare and initialize an object on the stack 
    MyTest testObj = {};
    testObj.print();

    return 0;
}

Я объявляю класс, чтобы иметь массив из 8 указателей на функции подписи "void functionname()". Когда я объявляю и инициализирую объект класса в main как MyTest testObj = {}; или же MyTest testObj;Я ожидал, что он будет инициализирован нулем, т.е. все указатели являются нулевыми указателями.

Тем не менее, компиляция с g++ 5.3.0 на моем компьютере с Windows 10 с g++ -m32 -o test -std=c++14 test.cpp && test Машина выдает на выходе:

myFunctions[0] = 76dd6b7d
myFunctions[1] = 00401950
myFunctions[2] = 0061ff94
myFunctions[3] = 004019ab
myFunctions[4] = 00401950
myFunctions[5] = 00000000
myFunctions[6] = 003cf000
myFunctions[7] = 00400080

Которые выглядят как неинициализированные значения из стека.

Если я перемещаю объявление объекта за пределы main (как глобальной переменной), оно снова печатает все нули.

Если я правильно понял cppreference, это потому, что у меня есть переменная со статической продолжительностью хранения, и поэтому она инициализируется нулями. Он инициализирует мой тип класса путем инициализации нулями всех нестатических данных-членов моего класса (т. Е. myFunctions) массив. Массив инициализируется нулевой инициализацией каждого его элемента, который в моем случае с указателем на функцию является нулевым указателем.

Почему он не инициализирует ноль мой объект в стеке, когда я объявляю его MyTest testObj = {};?

1 ответ

Решение

Следующие

MyTest testObj = {};

не является нулевой инициализацией для MyTest, но просто вызывает его конструктор по умолчанию. Страница cppreference объясняет, почему (выделение мое):

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

MyTest является типом класса, и имеет конструктор.


Определение конструктора с помощью

MyTest() = default;

вместо этого будет нулевая инициализация объекта.

Соответствующие стандартные цитаты (выделено мной) ниже.

Из [dcl.init # 6]:

Инициализировать значение объекта типа T означает:

  • если T является (возможно, cv-квалифицированным) типом класса без конструктора по умолчанию ([class.ctor]) или конструктора по умолчанию, предоставленного или удаленного пользователем, тогда объект инициализируется по умолчанию;

  • если T является (возможно, квалифицированным по cv) типом класса без предоставленного пользователем или удаленного конструктора по умолчанию, тогда объект инициализируется нулями, и проверяются семантические ограничения для инициализации по умолчанию, и если T имеет нетривиальный конструктор по умолчанию объект инициализируется по умолчанию;

  • ...

Из [dcl.init.list]:

Инициализация списка объекта или ссылки типа T определяется следующим образом:

  • ...

  • В противном случае, если список инициализаторов не имеет элементов и T является типом класса с конструктором по умолчанию, объект инициализируется значением.

Другие вопросы по тегам