可能重复:
In C++, is it still bad practice to return a vector from a function?
在表现方面,当需要返回更重的'来自函数的std::vector
或std::string
对象,建议使用此表单:
void func(std::vector<int> *dest)
{
}
而不是这种形式:
std::vector<int> func()
{
std::vector<int> arr;
// ...
return arr;
}
我假设第一种形式应该更快,但同时我经常看到第二种形式,Qt API通常会返回一个QString
,可能是因为它很多更方便或直观易用。
此外,我想知道是否有编译器优化可以在使用return语句时删除不必要的对象复制。
修改
今天仍然使用的任何热门编译器哪些不执行答案中提到的优化?
答案 0 :(得分:7)
建议使用[按指针传递]而不是[按值返回]?
否强>
A modern C++ compiler performs named return value optimisation (NRVO)这实际上意味着编译器可以在此处可靠地删除副本。没有复制。
请注意,这与您使用的C ++版本无关:C ++ 03和C ++ 11一样。在C ++ 11中唯一改变的是,当没有可以执行复制省略时,该语言使库更容易移出一个值(如此处所发生的)高效。
对于返回值,通常可以执行复制省略 - 在其他情况下更为相关(例如,按值传递参数)。但也有例外;以下代码不能使用命名返回值优化。它可以使用C ++ 11移动:
std::string foo() {
std::string one = "Foo";
std::string two = "Bar";
if (rand() % 2 == 0)
return one;
else
return two;
}
原因是现在两个代码路径返回不同的命名对象;这可以防止NRVO。
答案 1 :(得分:3)
按价值返回:
std::vector<int> func();
C ++允许复制省略用于这样的情况,除此之外,新的C ++定义了移动语义以使这些操作变得便宜。编译器通常很好地实现了这一点(使用copy elision,您的本地arr
实际上将最终构建在收件人调用站点变量中。这种情况也称为“返回值优化”。)
答案 2 :(得分:2)
允许RVO和NRVO的规则出现在ARM(1990)中, 所以如果任何编译器没有实现它们会很奇怪。
更重要的是,使用输出参数(指针或 对非const的引用非常笨拙。不要这样做, 直到剖析器说你真的有时间问题 因为复制了返回值。在这一点上, 过载函数,按照以下方式:
void func( std::vector<int>& dest )
{
// ...
}
std::vector<int> func()
{
std::vector<int> results;
func( results );
return results;
}
然后尝试两者,在探查器说你的位置 有问题,并选择解决问题的那个(如果 它有所不同。)
我实际上不得不这样做一次,但那是某个时候
1991年或1992年。从那以后,我没有必要这样做
几年来,我一直在努力做一些漂亮的表现
关键的东西;我们仍会定期返回std::vector
或我们的
在内部Matrix
课程。没有C ++ 11的优点,
因为并非所有目标编译器都支持它。
答案 3 :(得分:1)
std::vector<int> func();
使用C ++ 11,上面应该是你的功能。函数返回时,本地std::vector
对象将移动。如果可能,编译器可以省略 move 。
总之,不用担心。按价值返回。