RVO 应何时启动?
从下面的代码来看,如果发生了 RVO,我希望看到 2 个地址指向同一位置,但事实并非如此(我的编译器是 MS VC9.0)
#include <iostream>
#include <string>
std::string foo(std::string& s)
{
std::cout << "address: " << (unsigned int)(&s) << std::endl;
return s;
}
int main()
{
std::string base = "abc";
const std::string& s = foo(base);
std::cout << "address: " << (unsigned int)(&s) << std::endl;
std::cout << s << std::endl;
return 0;
}
在什么条件下应该发生 RVO?
顺便说一句,我的问题基于以下讨论: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
From the following code, If RVO has happened, I expect to see the 2 addresses pointing to the same location, however this is not the case (my compiler is MS VC9.0)
#include <iostream>
#include <string>
std::string foo(std::string& s)
{
std::cout << "address: " << (unsigned int)(&s) << std::endl;
return s;
}
int main()
{
std::string base = "abc";
const std::string& s = foo(base);
std::cout << "address: " << (unsigned int)(&s) << std::endl;
std::cout << s << std::endl;
return 0;
}
Under what conditions should RVO be happening?
btw, I'm basing my question on the following discussion: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
RVO 通常适用于返回未命名临时对象的情况,但如果返回先前创建的对象则不适用。
更通用的版本是 NRVO(命名返回值优化),它也适用于命名变量。
RVO generally applies when you return an unnamed temporary, but not if you return a previously created object.
A more general version is NRVO (Named return value optimization), which also works on named variables.
正确的答案是“只要编译器愿意”。标准并未强制(但允许)这种行为,并且其启动的确切条件因编译器和版本而异。
一般来说,编译器比你更聪明,并且会为你的最大利益而工作。不要质疑它。
C++0x 中的右值引用有点像 RVO 的手动版本。
编辑:仔细查看您的代码,您肯定误解了 RVO。因为您的参数是引用,所以函数的返回值不可能具有相同的地址。
The correct answer is "whenever the compiler pleases". Such behavior is not mandated (but is allowed) by the standard, and the exact conditions where it kicks in varies from compiler to compiler and version to version.
As a general rule, the compiler is smarter than you, and working in your best interest. Do not question it.
rvalue references in C++0x are sort of a manual version of RVO.
Edit: Looking closer at your code, you're definately misunderstanding RVO. Because your parameter is a reference, there is no way the return value of the function could have the same address.
我不知道完整的条件,但我相信您返回的是参数而不是函数中创建的实例,这一事实导致了示例中的问题。
对我来说,以下内容显示了两者的相同地址:
跟进 darid 的评论
键盘关于页面 记录了它使用 C++ 的 -fno-elide-constructors 。该选项的文档形成了 g++ 手册页状态:
在我的机器上,使用 -fno-elide-constructors 进行编译会阻止 RVO,但不使用 -fno-elide-constructors 进行编译则允许它。
I don't know the full conditions, but I believe the fact that you are returning a parameter and not an instance created in the function is causing the problem in your example.
For me, the following showed the same address for both:
Follow up to darid's comment
The codepad about page documents that for it use's the -fno-elide-constructors for C++. The documentation for this option form the g++ man page state:
On my machine, compiling with -fno-elide-constructors prevents RVO, but compiling without allows it.
您似乎误解了 RVO,请尝试这个示例(实际上是 NRVO):
You seem to misunderstand RVO, try this example (actually NRVO):