Вопрос по move-semantics, comma-operator, c++11, c++, return – Перемещение конструктора подавлено оператором запятой

13

Эта программа:

#include <iostream>
struct T {
    T() {}
    T(const T &) { std::cout << "copy constructor "; }
    T(T &&) { std::cout << "move constructor "; }
};
int main() {
    ([](T t) -> T { return t; })({}); std::cout << '\n';
    ([](T t) -> T { return void(), t; })({}); std::cout << '\n';
    ([](T t) -> T { return void(), std::move(t); })({}); std::cout << '\n';
}

при компиляции выходами gcc-4.7.1 (ссылка на сайт):

move constructor 
copy constructor 
move constructor 

Почему оператор запятой имеет такой эффект? Стандарт гласит:

5.18 Comma operator [expr.comma]

1 - [...] The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand [...]. If the value of the right operand is a temporary, the result is that temporary.

Я пропустил что-то, что позволяет оператору запятой влиять на семантику программы, или это ошибка в gcc?

яthink это означает, что именованные объекты обычно не могут быть перемещены (см. # 2 там), но есть явная лазейка дляreturn t; что он может нарушить правило именованного объекта и все равно двигаться (см. # 1). Но я не уверен. Если кто-то уверен, опубликуйте ответ. Mooing Duck

Ваш Ответ

2   ответа
8

t is локальная именованная переменная и, следовательно, lvalue. Оператор запятой ведет себя так, как задокументировано.

Скорее, вы должны спросить, почемуreturn t; позволяетt привязать к rvalue ссылке -thatнастоящая магия.

14

§12.8 [class.copy] p32

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. [...]

И копия elision, в свою очередь, разрешена, когда возвращаемое выражение являетсяname of an automatic object.

§12.8 [class.copy] p31

in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

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

Похожие вопросы