Разве тип C++ POD не может иметь конструктор?

StackOverflow https://stackoverflow.com/questions/5442717

  •  12-11-2019
  •  | 
  •  

Вопрос

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

struct A 
{
    int b;
};

A const a;

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

A const a = { 3 };

ИМХО, иметь такой конструктор — это нормально.

struct A 
{
    int b;

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

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


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

Это было полезно?

Решение

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

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

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

А в разделе §9/4 стандарта C ++ говорится,

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

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


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

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

Прочтите этот часто задаваемый вопрос : Что такое "тип капсулы"?

Другие советы

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

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

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

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

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

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

struct A
{
    int i_;
};

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

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

A a = make_A();
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top