我有一个函数可以std::string&就地修改左值引用,返回对输入参数的引用:
std::string& transform(std::string& input)
{
// transform the input string
...
return input;
}
Run Code Online (Sandbox Code Playgroud)
我有一个辅助函数,它允许在右值引用上执行相同的内联转换:
std::string&& transform(std::string&& input)
{
return std::move(transform(input)); // calls the lvalue reference version
}
Run Code Online (Sandbox Code Playgroud)
请注意,它返回一个右值引用.
我已经阅读了关于返回右值引用的SO的几个问题(这里和这里例如),并得出结论这是不好的做法.
根据我的阅读,似乎共识是因为返回值是 rvalues,再加上考虑RVO,只需按值返回就会有效:
std::string transform(std::string&& input)
{
return transform(input); // calls the lvalue reference version
}
Run Code Online (Sandbox Code Playgroud)
但是,我还读到返回函数参数会阻止RVO优化(例如此处和此处)
这使我相信std::string&从左值参考版本transform(...)的std::string返回值到返回值会发生副本.
那是对的吗?
保留我的std::string&& transform(...)版本会更好吗?
没有正确的答案,但按价值返回更安全.
我已经阅读了几个关于返回左值引用的SO的问题,并得出结论这是不好的做法.
返回对参数的引用会使调用者的合同强制转向
如果调用者传递临时值并尝试保存结果,则会获得悬空引用.
根据我的阅读,似乎共识是因为返回值是rvalues,再加上考虑RVO,只需按值返回就会有效:
按值返回会增加移动构建操作.其成本通常与物体的大小成比例.虽然通过引用返回只需要机器确保一个地址在寄存器中,但按值返回需要将参数中的几个指针归零std::string并将它们的值放入一个新的值中std::string以便返回.
它很便宜,但非零.
有些令人惊讶的是,标准库目前采用的方向是快速且不安全并返回参考.(我知道的唯一功能就是std::get来自<tuple>.)实际上,我向C++核心语言委员会提出了一个解决这个问题的建议,正在进行修订,就在今天我已经开始调查实施.但它很复杂,而且不确定.
Run Code Online (Sandbox Code Playgroud)std::string transform(std::string&& input) { return transform(input); // calls the lvalue reference version }
编译器不会在move这里生成.如果input根本不是参考,你return input;就会这样做,但它没有理由相信只会因为它是一个参数而transform返回input,并且它不会从rvalue引用类型中推断出所有权.(见C++14§12.8/ 31-32.)
你需要这样做:
return std::move( transform( input ) );
Run Code Online (Sandbox Code Playgroud)
或者等价的
transform( input );
return std::move( input );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2528 次 |
| 最近记录: |