从下面的代码中,如果发生了RVO,我希望看到两个地址指向相同的位置,但事实并非如此(我的编译器是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/
发布于 2010-01-08 20:31:33
RVO通常适用于返回未命名的临时对象,但不适用于返回以前创建的对象。
std::string foo() {
return std::string("hello world"); // RVO
}
std::string foo() {
std::string str("hello world");
bar();
return str; // Not RVO
}
std::string foo(std::string str) {
return str; // Not RVO
}一个更通用的版本是NRVO (命名返回值优化),它也适用于命名变量。
std::string foo() {
std::string str("hello world");
bar();
return str; // NRVO
}
std::string foo(std::string str) {
return str; // Not NRVO, as far as I know. The string is constructed outside the function itself, and that construction may be elided by the compiler for other reasons.
}
std::string foo(std::string str) {
std::string ret;
swap(ret, str);
return ret; // NRVO. We're returning the named variable created in the function
}发布于 2010-01-08 15:03:46
正确的答案是“只要编译器愿意”。这样的行为不是标准强制的(但允许的),并且它生效的确切条件因编译器和版本的不同而不同。
作为一般规则,编译器比你聪明,并且以你最大的利益工作。不要质疑它。
C++0x中的右值引用是RVO的一种手动版本。
RVO:仔细看看你的代码,你肯定误解了。因为您的参数是一个引用,所以函数的返回值不可能具有相同的地址。
发布于 2010-01-08 14:40:18
我不知道完整的条件,但我相信你返回的是一个参数,而不是在函数中创建的实例,这是导致你的例子出现问题的原因。
对我来说,下面显示了两者的相同地址:
#include <iostream>
#include <string>
std::string foo()
{
std::string s("rvo!");
std::cout << "address: " << (void *)(&s) << std::endl;
return s;
}
int main()
{
const std::string s = foo();
std::cout << "address: " << (void *)(&s) << std::endl;
std::cout << s << std::endl;
return 0;
}跟进darid的评论
它使用的codepad about page文档是C++的-fno-elide-构造函数。此选项的文档构成了g++手册页状态:
C++标准允许实现省略创建仅用于初始化相同类型的另一个对象的临时。指定此选项将禁用该优化,并强制G++在所有情况下调用复制构造函数。
在我的机器上,使用-fno-elide-constructors进行编译会阻止RVO,但不使用-fno-elide-constructors进行编译则会阻止RVO。
https://stackoverflow.com/questions/2025899
复制相似问题