返回值优化:我可以避免复制构造巨大的STL容器吗
Return value optimization: ho can I avoid copy construction of huge STL containers.
当我希望函数返回容器时:
vector<T> func(){
vector<T> result;
...
return result;
}
以以下方式使用:
vector<T> result = func();
为了避免复制容器的开销我经常编写函数,使它只返回一个容器的非常数实例。
void func(vector<T>& result){
result.clear();
...
result;
}
以以下方式使用:
vector<T> result;
func(result);
我的努力毫无意义吗?因为我可以确信编译器总是使用返回值优化?
这毫无意义。你提到的RVO类型被称为RVO(NRVO),大多数编译器都实现它
无论如何,在C++11中,vector
有move构造函数,所以即使NRVO没有应用,它仍然会被移动,而不是复制。
RVO不能得到保证,但在允许的情况下,优秀的编译器会使用它。
然而,问题是RVO只有在函数之外创建新对象时才有帮助。如果通过引用传递来重用同一向量,则可以利用其保留的容量来减少内存分配的数量。无论返回值存储在哪里,在函数内部创建的局部向量都需要在内部分配一个新的缓冲区。因此,通过引用传递向量可能会更高效,即使代码看起来不那么好看。
取决于编译器的使用年限。在C++11之前,除非编译器支持命名的返回值优化(并非所有较旧的编译器都支持),否则需要您的替代方法。此外,您还可以让函数返回对传递向量的引用。
从C++11开始,该语言支持move构造,并且标准容器具有可工作的move构造函数,因此您的第一种方法很好。纯粹主义者会坚持认为这样更好。实用主义者(他们意识到并不是每个人都能在没有巨大冒名顶替的情况下更新他们的编译器)会说,根据你的代码是否需要继续使用C++11之前和更高版本的编译器来选择解决方案。
我已经用gcc尝试过了。我意识到,在没有C++11标志的情况下进行编译时,我不能依赖NRVO。
由于我不喜欢第二个签名(函数引用容器),我提出了这个:
以其自然形式声明函数:
vector<T> func(){
vector<T> result;
...
return result;
}
当我不确定编译器和编译标志时,可以这样使用:
vector<T> result;
func().swap(result)
通过这种方式,可以获得所需的接口,并确保避免不可忽略的开销。
请注意,result
向量的容量是函数返回的向量的容量。如果要设置向量的容量,函数的正确接口是第二个接口。
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 使用2个键的cpp-stl::优先级队列排序不正确
- 在linux上调试巨大的C++项目
- 在STL容器中使用模板类
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 将stl字符串缩小到小于15个字符的容量
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 在STL - C++中按成绩对学生列表进行排序?
- GCC 和 Clang 代码性能的巨大差异
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- λ可以适应STL吗?
- 为什么使用 NDK 不能存在不同的 stl 实现?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 使用 char 分隔符解析C++中的字符串,但将可重复的字符保留为每个解析的子字符串 (C++ STL) 中的分隔符
- 在C++中迭代 STL 集时出现奇怪的问题<CStudent>
- 返回值优化:我可以避免复制构造巨大的STL容器吗