多返回点场景下C++的NRVO与复制省略问题问询
C++17中返回
std::tuple<std::vector<int>, std::vector<int>>的NRVO问题与优化方案 问题背景
编写了一段返回std::tuple<std::vector<int>, std::vector<int>>的C代码,疑惑在C17标准下是否会触发命名返回值优化(NRVO)。通过Compiler Explorer观察到vector出现两次内存分配与拷贝,想明确原因,并找到无需将列表作为参数传入的前提下,实现两个vector单次内存分配的修改方案。
原因分析
原代码中,tuple本身因返回值优化(RVO)仅进行了一次内存分配,但内部的vector却发生了拷贝。这是因为如果代码是直接构造临时tuple并返回,内部的vector对象属于临时对象,无法触发NRVO——编译器无法将这些临时vector的内存直接复用至函数返回的目标对象中,因此会产生额外的拷贝操作和内存分配。
优化方案
方案1:用std::move转移vector所有权
通过std::move将vector的所有权转移至返回的tuple中,避免拷贝操作,直接复用vector已分配的内存:
#include <tuple> #include <vector> std::tuple<std::vector<int>, std::vector<int>> get_vectors() { std::vector<int> vec1{1, 2, 3}; std::vector<int> vec2{4, 5, 6}; return {std::move(vec1), std::move(vec2)}; }
方案2:创建命名tuple触发NRVO
提前定义一个命名的tuple变量,直接在该tuple内部构造和填充vector,最后返回这个命名变量。编译器会触发NRVO,将tuple及其内部vector的内存直接复用至返回目标,完全避免拷贝:
#include <tuple> #include <vector> std::tuple<std::vector<int>, std::vector<int>> get_vectors() { std::tuple<std::vector<int>, std::vector<int>> result; auto& vec1 = std::get<0>(result); auto& vec2 = std::get<1>(result); // 按需填充vector内容 vec1.reserve(3); vec1.push_back(1); vec1.push_back(2); vec1.push_back(3); vec2.reserve(3); vec2.push_back(4); vec2.push_back(5); vec2.push_back(6); return result; }
内容的提问来源于stack exchange,提问作者Ramneet Singh
相关产品推荐
相关产品推荐

