c++ c++11 c++17 rvo structured-bindings

c++ - ¿Por qué los enlaces estructurados deshabilitan RVO y mueven en la declaración de retorno?



c++11 c++17 (1)

Sin embargo, ¿por qué el movimiento implícito NO se puede esperar tampoco?

Por la misma razón por la que elision está desactivado: porque es una referencia , no el nombre de un objeto independiente. Cada uso de second es esencialmente equivalente a decir obj.whatever o get<1>(obj) (aunque en este último caso, almacenamos la referencia). Y no hay movimiento implícito de ninguna de esas expresiones.

El enlace estructurado es para acceder a subobjetos del objeto dado. No se pueden omitir devoluciones de subobjetos, ni se puede mover implícitamente de ellos. Por lo tanto, no puede evitar los nombres de enlace estructurado ni moverlos implícitamente.

Supongamos que tenemos una clase llamada AAA que admite tanto copiar / mover :

class AAA { public: AAA() = default; ~AAA() = default; AAA(const AAA& rhs) { std::cout << "Copy constructor" << std::endl; } AAA(AAA&& rhs) { std::cout << "Move constructor" << std::endl; } };

En el siguiente código, get_val devuelve el second :

AAA get_val() { auto [ first, second ] = std::make_tuple(AAA{}, AAA{}); std::cout << "Returning - " << std::endl; return second; } auto obj = get_val(); std::cout << "Returned - " << std::endl;

Ahora se copia el second , imprimiendo la siguiente salida:

... Returning - Copy constructor Returned -

Esto es desafortunado, porque mi expectativa del resultado es que no hay una llamada para copiar el constructor, o al menos se movió implícitamente .

Para evitar copiar, tendré que aplicar explícitamente std::move en él.

return std::move(second);

Entonces recibiría el resultado de:

... Returning - Move constructor Returned -

Supongo que la razón por la que RVO no se ejecuta es que probablemente los compiladores verían el second como una referencia, mientras que get_val devuelve prvalue.

Sin embargo, ¿por qué el movimiento implícito NO se puede esperar tampoco? El uso explícito de std::move en la declaración de devolución no parece intuitivo en este caso particular, porque generalmente no desea que RVO, que en la mayoría de los casos es una mejor optimización que mover, desaparece accidentalmente .

Probado por ambos compiladores gcc y clang con -O3 .

Demo en vivo