我一直在研究右值参考(对我来说是一个新概念),我对以下类函数中收到的警告感到困惑......
string&& Sampler::Serial() const {
stringstream ss;
.
. [assemble a string value using data members]
.
return ss.str();
}
此编译成功,但出现以下警告......
..\Metrics\Sampler.cpp:71:16: warning: returning reference to temporary [-Wreturn-local-addr]
return ss.str();
^
我完全知道我正在返回一个临时的,正如我使用右值引用作为我的返回类型这一事实所证明的那样。代码似乎在执行时运行正常,那么为什么这需要编译器警告?
similar questions的标准答案似乎是复制返回值而不是使用引用,但是当我可以使用右值引用移动它时,为什么要复制潜在的大量临时数据?这不是它被发明的原因吗?
答案 0 :(得分:8)
您不移动您的数据。您正在创建一个本地对象,创建对该本地对象的引用,销毁该本地对象,然后仍然使用该引用。
您应该按照您已经找到的值返回。但不是复制,而是移动数据。这是确保您不会复制大量数据的安全方法。
Source: local data frame [2 x 6]
Groups: id1, id2
date ind id1 id2 code var
1 2015-07-02 1 z z2 2 0.7614406
2 2015-07-03 1 z z2 2 0.5015336
注意:std::string Sampler::Serial() const {
std::stringstream ss;
.
. [assemble a string value using data members]
.
return std::move(ss.str());
}
在技术上是多余的,因为std::move
已经返回一个右值,因此已经移动了。无论如何,我建议把它留下。这种方式适用于任何情况,因此您不必考虑使用哪种表单:如果您想移动,请写ss.str()
。
正如T.C.所指出的那样,一般来说,虽然不是你的情况,但这可以防止RVO。在RVO可行的情况下以及编译器无论如何都隐式使用移动的情况下,都不需要明确地编写move
。例如:
move
在这里,读者已经清楚std::string f() {
std::string x;
...
return x; // not std::move(x)
}
是一个局部变量。 C ++代码在不编写x
的情况下返回局部变量是正常的,因为编译器将完全忽略move
局部变量并直接在返回槽中构造x
对象(无论对您的平台意味着什么),或者编译器将隐式使用std::string
的移动构造函数。
答案 1 :(得分:5)
这类似于将左值引用返回到局部变量,并使您快速跟踪未定义的行为。
无论是返回左值引用还是右值引用,您仍然引用将在函数退出时销毁的内存。
Rvalue引用返回类型应该保留用于引用一个寿命比函数长的对象的情况,但是你不再需要它,所以为了提高效率,它可以被移动。例如,您可能遇到临时存储某些数据的情况,但客户可以选择“窃取”您的数据。在这种情况下,返回对数据的右值引用是合理的。
答案 2 :(得分:4)
您返回对作为对象(由git log
返回)的(rvalue)引用,该对象在作用域末尾被销毁的临时对象(str()
)。
您应该返回对象:
ss