Разве C ++ POD-тип не может иметь конструктора? - PullRequest
17 голосов
/ 26 марта 2011

У меня есть класс и переменная const.

struct A 
{
    int b;
};

A const a;

Класс A является POD и может быть инициализирован следующим образом.

A const a = { 3 };

ИМХО, это выглядит нормальноесть конструктор, подобный этому.

struct A 
{
    int b;

    A(int newB) : b(newB)
    {
    }
};

Но Clang предполагает A как неагрегированный тип.Почему у меня не может быть такого конструктора?Или я должен сделать что-то еще?


Я изменил вопрос, чтобы представить свое первоначальное значение.Я написал struct как class по ошибке, и извините за @Johannes за путаницу:)

Ответы [ 3 ]

18 голосов
/ 26 марта 2011

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

POD на самом деле является агрегатным типом (см. Следующую цитату). Так что же такое совокупность? Стандарт C ++ говорит в разделе §8.5.1 / 1,

Агрегат - это массив или класс (пункт 9) с без объявления пользователя конструкторы (12.1), не частные или защищенные нестатические члены данных (пункт 11), без базовых классов (пункт 10) и без виртуальных функций (10.3).

А в разделе §9 / 4 стандарта C ++ сказано:

[....] POD-структура - это агрегатный класс , который не имеет нестатических данных. члены типа non-POD-struct, не POD-объединение (или массив таких типов) или ссылка, и имеет не определено пользователем оператор присвоения копии и нет определяемый пользователем деструктор . Точно так же, POD-union - это совокупный союз, который не имеет нестатических членов данных типа не POD-структура, не POD-объединение (или массив таких типов) или ссылки, и не имеет пользовательского назначения копирования оператор и не определены пользователем деструктор . POD класс - это класс это либо POD-структура, либо POD-союз.

Из этого также ясно, что класс / структура / объединение POD не может иметь определяемый пользователем оператор присваивания и определяемый пользователем деструктор также.


Однако существуют и другие типы POD. Раздел § 3.9 / 10 гласит:

Арифметические типы (3.9.1), типы перечисления, типы указателей и указатель на типы элементов (3.9.2) и cv-квалифицированные версии этих типов (3.9.3) все вместе называются скалярными типы. Скалярные типы, типы POD-структуры, Типы POD-union (раздел 9), массивы такие типы и cv-квалифицированные версии из этих типов (3.9.3) вместе называемые типы POD .

Прочтите этот FAQ: Что такое "тип POD"?

5 голосов
/ 26 марта 2011

Класс A является POD и может быть инициализирован следующим образом

Извините, это неправильно.Поскольку b является закрытым, класс не является POD.

Но Clang принимает A как неагрегированный тип.Почему у меня не может быть такого конструктора?Или я должен сделать что-то еще?

Это ограничение C ++, поскольку оно существует в настоящее время.C ++ 0x больше не будет иметь этого ограничения.В то время как в C ++ 0x ваш тип также не является POD, ваша инициализация будет работать (при условии, что вы сделаете этот конструктор public).

(Кроме того, я думаю, что вам лучше использовать здесь«агрегат». Требование использования { ... } заключается в том, что ваш класс является агрегатом. Он не обязательно должен быть POD).

2 голосов
/ 26 марта 2011

Другие ответы довольно хорошо описывают правила POD. Если вы хотите получить стиль инициализации, аналогичный конструктору для POD, вы можете использовать функцию make_-стиля, например:

struct A
{
    int i_;
};

A make_A(int i = 0) 
{
    A a = { i }; 
    return a; 
}

теперь вы можете получить инициализированные экземпляры POD, такие как:

A a = make_A();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...