Является ли С++ значением инициализации POD typedef?

Выполняет ли С++ инициализацию на простой POD typedefs?

Полагая

typedef T* Ptr;

делает

Ptr()

выполнить инициализацию значения и гарантировать равную (T*)0?

например.

Ptr p = Ptr();
return Ptr();

Ответы

Ответ 1

Это так. Для типа T, T() значение инициализирует "объект" типа T и дает выражение rvalue.

int a = int();
assert(a == 0);

То же самое для под-классов:

struct A { int a; };
assert(A().a == 0);

Также верно для некоторых не-POD-классов, у которых нет объявленного конструктора:

struct A { ~A() { } int a; };
assert(A().a == 0);

Так как вы не можете сделать A a() (вместо этого создается объявление функции), boost имеет класс value_initialized, позволяющий обойти что, и С++ 1x будет иметь следующий, альтернативный синтаксис

int a{};

В сухих словах Стандарта это звучит как

Выражение T(), где T является спецификатором простого типа (7.1.5.2) для типа объекта без массива или типа (void cv-qualified) void, создает rvalue указанного типа, который инициализируется значением

Так как typedef-name - это имя типа, которое является самим спецификатором простого типа, это работает отлично.

Ответ 2

#include <iostream>
struct Foo {
    char bar;
    char baz;
    char foobar;
    // the struct is a POD
    //virtual void a() { bar='b'; }
};

int main() {
    Foo o1;
    Foo o2 = Foo();

    std::cout << "O1: " << (int)o1.bar <<" "<< (int)o1.baz <<" "<< (int)o1.foobar << std::endl;
    std::cout << "O2: " << (int)o2.bar <<" "<< (int)o2.baz <<" "<< (int)o2.foobar << std::endl;
    return 0;
}

Вывод:

O1: -27 -98 0

O2: 0 0 0

Adding() распространяет вызовы инициализации для всех членов POD. Недовольство виртуального метода изменяет вывод:

O1: -44 -27 -98

O2: -71 -120 4

Однако добавление деструктора ~ Foo() не подавляет инициализацию, хотя создает объект не-POD (выход аналогичен первому).