21

В каких случаях происходит инициализация нулями и в каких нет?

Kioqps
  • 213
  • Смотря чего. Для инициализации участка памяти, например, существуют функции стандартной библиотеки(calloc как альтернатива malloc, к примеру). – AseN Jan 25 '16 at 08:41
  • Мне интересны все возможные случаи инициализации в с++, гугл не помог или я не так гуглил. – Kioqps Jan 25 '16 at 08:51
  • 2
    А мне вот помог гугл – ixSci Jan 25 '16 at 08:56
  • Ну там же не все случаи. – Kioqps Jan 25 '16 at 09:01

3 Answers3

12

Инициализация нулями (zero-initialization) применяется в трех случаях:

1) Переменные со статическим и потоковым временем хранения (static/thread storage duration), перед тем как для них производится любая другая инициализация.
Сюда входят переменные, объявленные с помощью ключевых слов thread_local, static, а также глобальные переменные.

thread_local int a;
int b;
struct S {
  void f() {
    static int c;
  }
  static int d;
};
int S::d;

2) При инициализации значением (value-initialization), если тип не является классом (class или struct), и не является массивом.

union U { int a; float b; };
void f(int, U);

f(int(), U());

3) Элементы массива char, для которых нет инициализаторов:

char a[5] = "123"; // a[3] и a[4] будут использованы нулями.

Более подробно можно прочитать на cppreference.

Abyx
  • 31,143
  • А как же массивы? int a[16]={0}; – Qwertiy Jan 25 '16 at 11:01
  • А char чем особенный? – Qwertiy Jan 25 '16 at 11:11
  • @Abyx en.cppreference.com/w/cpp/language/default_initialization, там пишут object в таком странном контексте как будто это понятие включает в себя и класс и обычный примитивный тип. Верно ли это? – Kioqps Jan 25 '16 at 13:44
  • 1
    @Kioqps, да это нормально: «The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a region of storage.» Standard C++ [intro.object] p1 – ixSci Jan 25 '16 at 13:55
  • @ixSci , я нашел стандарт с++, но никак не могу найти раздел об инициализаторах. Ткните пожалуйста, умоляю :D – Kioqps Jan 25 '16 at 15:16
  • 1
    @Kioqps, поиск по pdf ->intro.object. Ну или секция 1.8, самый первый пункт. – ixSci Jan 25 '16 at 15:17
  • @ixSci , а чем отличается variable от object? Тем что variable именованная? – MrPrank Jan 25 '16 at 19:08
  • @MrPrank, если очень грубо, то — да. Подробнее можно тут глянуть – ixSci Jan 26 '16 at 05:52
5

Нулями инициализируются переменные, расположенные в статической памяти, а переменные, расположенные в автоматической памяти (стеке) не инициализируются.

Hermann Zheboldov
  • 1,136
  • 10
  • 22
  • При обьявлении класса в стеке (локального, не ссылки на класс) вызывается конструктор класса. Если конструктор делает "очистку", то да. – nick_n_a Jan 25 '16 at 10:14
4

Самый заковыристый момент с конструкторами по-умолчанию. Если конструктор по-умолчанию определен компилятором неявно, то при вызове его со скобками зануление выполняется, а без скобок не выполняется.

У меня на эту тему была проблема с классом std::array который по стандарту не имеет каких-либо явных конcтрукторов. Так вот, следующий код ожидал зануление и был ошибочный:

typedef std::array<unsigned char, 16> Bytes;

auto block = Bytes;  // в массиве муссор

А этот правильный:

auto block = Bytes(); // в массиве нули

Правда в моем случае дело усугубилось еще и тем, что волшебный VC2012 в отладочной сборке выполнял зануление для первого варианта, а в выпускной нет. Поэтому я не сразу догадался проверить конструктор.

Cerbo
  • 6,863