这个网站上有很多关于返回值优化的问题(我想这是一个相当令人困惑的话题),但我似乎找不到一个可以回答我的特定问题的问题。如果我的代码如下所示:
returnType function() { stuff....}
void someOtherFunction()
{
returnType var = function();
more stuff...
}
我被告知编译器可能决定在 someOtherFunction()
中不使用 returnType
的两个实例。从逻辑上讲,我希望 function()
会生成一个 returnType
类型的对象,而 someOtherFunction()
会通过复制构造函数接收该值(重载与否)转换为临时值。然后,我希望临时值通过赋值(可以重载,理论上可以具有任何功能!)复制到 var
中,该值之前已通过默认构造函数初始化。
我在这里看到了一个潜在的问题。如果 someOtherFunction()
中没有 returnType
的临时拷贝会怎样? var
是否必须通过复制构造函数直接用 function()
的返回值填充?如果是这样,赋值运算符不会被调用吗?如果是这样,并且如果赋值运算符被重载,那不会改变程序的功能吗?如果是这样,这是否意味着程序员有责任确保 =
始终与复制构造函数执行相同的操作?而且我讨厌运行这么长的一系列问题,但是如果是这样,为什么 C++ 允许您定义复制构造函数来执行赋值以外的操作?
最佳答案
I would then expect that temporary value to be copied via assignment (which could be overloaded and in theory could have any kind of functionality!) into var, which would have previously been initialized via the default constructor.
嗯,对于初学者来说,这是完全错误的。
int x = 0;
int x(0);
这两行是同一个东西——构造函数调用。有一些区别——我相信第一个不能调用显式构造函数——但它们是相同的函数调用。没有默认构造,也没有赋值运算符调用。它们都是直接构造。
基本上,标准说“如果您在复制构造函数中复制对象之外的其他操作,这是您自己的愚蠢错误,当优化器消除调用时,您的程序没有表现出预期的行为,我笑了”。当然,这些是我自己的意译,但标准对允许优化器消除拷贝非常明确。在 C++0x 中,这也适用于移动。
你上面的代码片段是真的
returnType function() { stuff....}
void someOtherFunction()
{
returnType var(function());
more stuff...
}
这不是优化的版本,它就是这样。 从不调用赋值运算符。使用 NRVO,它看起来像
void function(void* mem) { // construct return value into mem
new (mem) returnType;
// Do shiz with returnType;
}
void someOtherFunction() {
// This doesn't respect some other things like alignment
// but it's the basic idea
char someMemory[sizeof(returnType)];
function(someMemory);
// more stuff here
}
当然,即使在异常情况下,编译器也必须处理破坏对象,并确保所有别名的类型和对齐方式正确,以及其他一些我在我的文章中没有处理的事情示例,但希望您能了解一般要点。
关于C++关于返回值优化的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6879482/