我有一个看起来像这样的函数:
// Fetch 1 MB of data
void GetData(std::vector<char> & outData);
1MB被夸大了,但我只是想说明最好避免不必要的副本。
如果我添加此重载:
std::vector<char> GetData()
{
std::vector<char> result;
GetData(result);
return result;
}
那么RVO有多大可能会开始?
答案 0 :(得分:7)
对于大多数合理的近期编译器(例如,VS 2005或更新版本,gcc 3.4或更新版本),它基本上是肯定的。我只说“最”,因为我没有测试现有的每个编译器。我在过去5年左右看过的每一个新编译器都包含它。
答案 1 :(得分:3)
RVO很可能会参与进来,因为这是一个非常简单的优化,已经有很长一段时间了。但是,为了使这段代码在中等高性能代码中真正具有实用价值,您需要NRVO。 NRVO更难以接触,因为它相对较新。但它是可用的。例如,MS编译器从VS2005开始实现它。
答案 2 :(得分:2)
我认为没有任何标准答案:它取决于你的编译器及其能力。
如果您正在考虑为方便起见而实现这一点,那么为什么不只是尝试编译器并查看程序集或对其进行概要分析,看看会发生什么?关于你的编译器实际做了什么的经验证据可能比猜测一些编译器可能做什么或不做什么更好。
答案 3 :(得分:0)
那么RVO有多大可能会开始?
思考软件开发人员的工作,而不是编译器。
编译器通常经过优化,可以很好地运行良好的代码 - 而不是糟糕的代码。
就个人而言,我使用第一种形式。通常使用指针而不是引用 - 突出显示参数是输出的事实,而不是输入。
答案 4 :(得分:0)
另外,请注意:
std::vector<char> GetData()
{
// :
return result;
}
vector<char> x = GetData();
在被叫方中,result
被复制到“返回值”,然后在调用者中,“返回值”被复制到x
。 NRVO可以摆脱其中一个副本,但不能同时消除这两个副本。编译器必须至少调用一次复制文件,因为它必须假定复制文件具有必须完成的副作用。