Рассмотрим следующий пример:
#include <cstdio>
class object
{
public:
object()
{
printf("constructor\n");
}
object(const object &)
{
printf("copy constructor\n");
}
object(object &&)
{
printf("move constructor\n");
}
};
static object create_object()
{
object a;
object b;
volatile int i = 1;
// With #if 0, object copy constructor is called; otherwise, its move constructor.
#if 0
if (i)
return b; // moves because of the copy elision rules
else
return a; // moves because of the copy elision rules
#else
// Seems equivalent to the above, but behaves differently.
return i ? b : a; // copies (with g++ 4.7)
#endif
}
int main()
{
auto data(create_object());
return 0;
}
И рассмотрим этот бит из рабочего проекта С++ 11, n3337.pdf, 12.8 [class.copy], пункт 32:
Когда критерии для выполнения операции копирования выполняются или выполняются, за исключением того факта, что исходный объект является параметром функции, , а подлежащий копированию объект определяется значением lvalue, разрешением перегрузки для выбора конструктор для копии сначала выполняется так, как если бы объект был обозначен rvalue. Если сбой при перегрузке или если тип первого параметра выбранного конструктора не является ссылкой rvalue на тип объекта (возможно, с квалификацией cv), разрешение перегрузки выполняется снова, считая объект как lvalue. [Примечание. Это двухступенчатое разрешение перегрузки должно выполняться независимо от того, произойдет ли копирование. Он определяет вызывающий конструктор, если elision не выполняется, и выбранный конструктор должен быть доступен, даже если вызов отменяется. -end note]
Таким образом, если мы используем #if 1
в примере, сначала создается конструктор перемещения при возврате объекта, а затем конструктор копирования. Поскольку у нас есть конструктор перемещения, он используется вместо конструктора копирования.
В последнем выражении return
в create_object()
, однако, мы заметили, что конструктор перемещения не используется. Является ли это или не является нарушением языковых правил? Требует ли язык, чтобы конструктор перемещения использовался в последнем выражении return
?