yo quería comprobar el caso de las siguientes optimizaciones funcionan como se esperaba:Condiciones para la elisión de copia?
- RVO
- Named RVO
- Copia elisión al pasar un argumento por valor
así que escribí este pequeño programa :
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <vector>
struct Foo {
Foo(std::size_t length, char value) : data(length, value) { }
Foo(const Foo & rhs) : data(rhs.data) { std::cout << "*** COPY ***" << std::endl; }
Foo & operator= (Foo rhs) {
std::cout << "*** ASSIGNMENT ***" << std::endl;
std::swap(data, rhs.data); // probably expensive, ignore this please
return *this;
}
~Foo() { }
std::vector<char> data;
};
Foo TestRVO() { return Foo(512, 'r'); }
Foo TestNamedRVO() { Foo result(512, 'n'); return result; }
void PassByValue(Foo inFoo) {}
int main()
{
std::cout << "\nTest RVO: " << std::endl;
Foo rvo = TestRVO();
std::cout << "\nTest named RVO: " << std::endl;
Foo named_rvo = TestNamedRVO();
std::cout << "\nTest PassByValue: " << std::endl;
Foo foo(512, 'a');
PassByValue(foo);
std::cout << "\nTest assignment: " << std::endl;
Foo f(512, 'f');
Foo g(512, 'g');
f = g;
}
Y lo compilé con optimizaciones en abled:
$ g++ -o test -O3 main.cpp ; ./test
Esta es la salida:
Test RVO:
Test named RVO:
Test PassByValue:
*** COPY ***
Test assignment:
*** COPY ***
*** ASSIGNMENT ***
De acuerdo con la salida y el trabajo RVO RVO nombrado como era de esperar. Sin embargo, la elisión de copia no se realiza para el operador de asignación y cuando se llama al PassByValue
.
¿No se permite copiar elision en los constructores de copia definidos por el usuario? (Sé que RVO está explícitamente permitido por el estándar, pero no sé sobre la elisión de copia al pasar por el valor). ¿Hay alguna manera de verificar la elisión de copia sin definir los constructores de copia?
Para que quede claro, (N) RVO * is * copy elision. No son las únicas formas, pero decir que su ejemplo muestra que la elisión de copia no se realiza es inexacto. –
La elisión de Cooy generalmente está permitida para todos los objetos temporales, pero no para objetos con nombre o vinculados a referencia. Parece que gcc realiza precisamente los permitidos. –
@Dennis Zickefoose gracias, arreglé el texto. – StackedCrooked