Инициализаторы элементов нестатического ввода С++, немного запутанные
Я немного смущен, почему следующий код делает то, что он делает:
class Base
{
public:
Base() = default;
Base(const Base &) =delete;
Base &operator=(const Base &) = delete;
Base(const char*) {}
};
class Holder
{
public:
Holder() = default;
private:
// Base b = Base();
Base b2 = {};
};
int main()
{
Holder h;
}
в этом воплощении, он компилируется, однако, если я не комментирую Base b = Base();
, он дает следующую ошибку:
main.cpp:15:17: error: use of deleted function 'Base::Base(const Base&)'
Base b = Base();
^
main.cpp:5:6: note: declared here
Base(const Base &) =delete;
^
и я просто не могу найти в стандарте, почему он пытается вызвать конструктор копирования для инициализатора Base b = Base()
, и почему он не вызывает Base b2 = {}
... или это только один из тех немного неясности, которая скрыта в нескольких словах в абзаце где-то?
Можете ли вы дать (краткое) объяснение, почему это происходит?
(coliru: http://coliru.stacked-crooked.com/a/c02ba0293eab2ce5)
Ответы
Ответ 1
Это потому, что концептуально эта строка построена из Base()
, для которой требуется конструктор copy/move. Вероятная причина, по которой вы не знали об этом, заключается в том, что это выражение обычно вызывает копирование elision: стандартная оптимизация. Это один из тех, что были С++.
(31.3) - когда объект временного класса, который не был связан с ссылка (12.2) будет скопирована/перенесена в объект класса с тем же cv-unqualified тип, операция копирования/перемещения может быть опущена построение временного объекта непосредственно в цель пропущено копирование/перемещение.
Как работает Base b2 = {}
, см.
(3.4) - В противном случае, если в списке инициализаторов нет элементов, а T - тип класса с конструктором по умолчанию, объект значение инициализации.
Вы можете просто сделать Base b;
.
Ответ 2
T object = {arg1, arg2, ...};
является синтаксисом для инициализации списка. Нет никакого копирования.
T object = T()
не является инициализацией списка. Правый операнд создает временную инициализацию значения, а object
инициализируется движением или копией. Перемещение и копирование могут быть отменены, но тип должен быть подвижным или скопированным, иначе это не разрешено.