我正在阅读Dave Abrahams关于复制省略和RVO的Want Speed? Pass by Value.。而且我想知道为什么我们需要复制省略?
我被告知过多次你应该通过const引用传递函数参数以避免复制(我读过的几乎每一本c ++书都告诉我这个)。
假设我们有两个功能:
int f1(const string &s);
int f2(string s);
如果实际参数是右值,则两个函数都将避免复制。但如果实际参数是左值,则只能在f1中避免复制,而不是在f2中。那么为什么我们需要这个功能呢?
答案 0 :(得分:11)
如果您还需要副本,请按值传递。是否选择f1的签名或f2的签名取决于函数的内容。例如,在这种情况下,您将使用const引用:
int f1(const string& s) {
return s.size();
}
但在这种情况下你会通过值传递:
int f2(string s) {
sort(s.begin(), s.end());
s.erase(unique(s.begin(), s.end()), s.end());
return s.size();
}
因为替代方案是:
int f2(const string& s) {
string temp(s);
sort(temp.begin(), temp.end());
temp.erase(unique(temp.begin(), temp.end()), temp.end());
return temp.size();
}
答案 1 :(得分:1)
RVO不适用于您的示例,因为返回值为int
。
string f1(const string &s) {
string ret = s; // always makes a copy
ret += 'x';
return ret; // makes a copy pre-C++11 if no RVO
}
Tally:在C ++ 03中有1-2个拷贝,在C ++ 11中只有1个拷贝(如果禁用了elision),这个动作可能会退化为std::string
之外的其他类的副本。
string f2(string s) { // calling makes a copy if lvalue or no elision
s += 'x';
return s; // makes a copy pre-C++11 if no RVO
}
理货:C ++ 03中0-2份,或C ++ 11中0-1份。
正如其他人所说,当你想把对象作为一个纯值来操作时传递值,没有任何引用语义。
const &
是一个熟悉的习语,但就语言语义而言,它有点像kludge。当你根本不想要参考时,你可以使用它; &
仅用于使const
在参数定义中有意义。如果您想修改参数(但仅限于本地),则const
并不真正适用,&
也会消失。
答案 2 :(得分:0)
f2
通过其签名发出信号,无论你传递给我什么,我都会处理我自己的对象副本。有用,如果f2
将以不可逆的方式修改对象(例如通过移动窃取它的资源),或者在某些并发方案中。不可否认,c ++ 11为(已经令人困惑的)c ++类型系统增加了新的混乱程度,但一旦你想到它就会有很多意义......