考虑以下代码:
LargeObject getLargeObject()
{
LargeObject glo;
// do some initialization stuff with glo
return glo;
}
void test()
{
LargeObject tlo = getLargeObject();
// do sth. with tlo;
}
一个简单的编译器将在getLargeObject()堆栈上创建本地LargeObject glo,然后在返回时将其分配给test()中的tlo,这涉及复制操作。
但是,一个聪明的编译器难道不应该意识到glo将被分配给tlo并因此仅仅首先使用tlo的内存来避免复制操作吗?结果(在功能上)类似:
void getLargeObject(LargeObject &lo)
{
// do init stuff
}
void test()
{
LargeObject lo;
getLargeObject(lo);
}
我的猜测是,编译器会执行类似的操作。但是总能做到吗?在某些情况下无法像这样进行优化吗?我怎么知道我的返回值是否被复制?
最佳答案
你的猜测是正确的。是的,在某些情况下它无法完成,例如:
LargeObject getLargeObject()
{
LargeObject glo1, glo2;
// do some initialization stuff
if (rand() % 2)
return glo1;
return glo2;
}
由于编译器无法知道将返回值使用glo1还是glo2,因此无法在此完成。
“我怎么知道我的返回值是否被复制?”
我可以想到两种方式。您可以创建嘈杂的副本构造函数。也就是说,复制构造函数具有一些可检测到的副作用,例如打印消息。然后当然是组装的旧外观。