Mor*_*ten 71 c++ return-value stdvector
在函数中返回std :: vector时复制了多少数据,将std :: vector放在free-store(在堆上)并返回指针的优化程度是多少,即:
std::vector *f()
{
std::vector *result = new std::vector();
/*
Insert elements into result
*/
return result;
}
Run Code Online (Sandbox Code Playgroud)
效率高于:
std::vector f()
{
std::vector result;
/*
Insert elements into result
*/
return result;
}
Run Code Online (Sandbox Code Playgroud)
?
Naw*_*waz 102
在C++ 11中,这是首选方式:
std::vector<X> f();
Run Code Online (Sandbox Code Playgroud)
也就是说,按价值返回.
对于C++ 11,它std::vector具有移动语义,这意味着函数中声明的局部向量将在返回时移动,在某些情况下甚至可以由编译器省略移动.
Ste*_*sop 49
你应该按价值回报.
该标准具有特定的功能,以提高按价值返回的效率.它被称为"复制省略",更具体地说是"命名返回值优化(NRVO)".
编译器没有实现它,但随后又编译器不具备实现内联函数(或执行任何优化的话).但是,如果编译器没有进行优化,标准库的性能可能会非常差,并且所有严格的编译器都会实现内联和NRVO(以及其他优化).
应用NRVO时,以下代码中不会复制:
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
Run Code Online (Sandbox Code Playgroud)
但是用户可能想要这样做:
std::vector<int> myvec;
... some time later ...
myvec = f();
Run Code Online (Sandbox Code Playgroud)
复制省略不会阻止复制,因为它是一个赋值而不是初始化.但是,您仍应按值返回.在C++ 11中,赋值通过不同的东西进行优化,称为"移动语义".在C++ 03中,上面的代码确实会产生副本,虽然理论上优化器可能能够避免它,但实际上它太难了.所以myvec = f()在C++ 03中你应该这样写:
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
Run Code Online (Sandbox Code Playgroud)
还有另一种选择,即为用户提供更灵活的界面:
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
Run Code Online (Sandbox Code Playgroud)
然后,您还可以支持现有的基于矢量的界面:
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
Run Code Online (Sandbox Code Playgroud)
如果现有代码的使用方式比预先固定的数量更复杂,那么这可能比现有代码效率低reserve().但是如果您现有的代码基本上push_back反复调用向量,那么这个基于模板的代码应该是一样好的.