Когда агрегатная инициализация допустима в C ++ 11?

Допустим, у нас есть следующий код:

#include 
#include 

struct A
{
  A() {}
  A(const A&) { std::cout << "Copy" << std::endl; }
  A(A&&) { std::cout << "Move" << std::endl; }
  std::string s;
};

struct B
{
  A a;
};

int main()
{
  B{A()};
}

Здесь, я полагаю, struct A не является агрегатом, поскольку в нем есть оба нетривиальных конструкторы, а также член std :: string , который, как я полагаю, не является агрегатом. Предположительно это означает, что B также не является агрегатом.

Тем не менее, я могу агрегировать инициализировать B. Кроме того, это можно сделать без вызова конструктора копирования или перемещения (например, C ++ 0x GCC 4.5 .1 на ideone ).

Такое поведение кажется полезной оптимизацией, особенно для объединения типов больших стеков, у которых нет дешевых ходов.

Мой вопрос: когда такая агрегированная инициализация допустима в C ++ 0x?

Правка + дополнительный вопрос:

DeadMG ниже ответил следующим образом:

Это вообще не агрегированная инициализация, это единообразная инициализация, которая в данном случае означает вызов конструктора, а отсутствие копирования или перемещения, вероятно, выполняется RVO и NRVO.

Обратите внимание, что когда я меняю B на следующее:

struct B
{
  A a;
  B(const A& a_) : a(a_) {}
  B(A&& a_) : a(std::move(a_)) {}
};

Выполняется перемещение.

Итак, если это просто единообразная инициализация, просто вызывается конструктор и ничего особенного не делает, тогда как мне написать конструктор, позволяющий опустить перемещение?

Или GCC просто не отменяет перемещение здесь, когда это допустимо, и если да, существует ли параметр компилятора и оптимизации, который отменяет перемещение?

10
задан Xeo 19 December 2011 в 00:49
поделиться