Подтвердить что ты не робот

Не может ли тип С++ POD иметь какой-либо конструктор?

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

struct A 
{
    int b;
};

A const a;

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

A const a = { 3 };

IMHO, он выглядит так, чтобы иметь такой конструктор.

struct A 
{
    int b;

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

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


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

4b9b3361

Ответ 1

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

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

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

И в разделе § 9/4 из С++ Standard говорится:

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

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


Существуют, однако, и другие типы 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" ?

Ответ 2

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

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

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

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

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

Ответ 3

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

struct A
{
    int i_;
};

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

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

A a = make_A();