You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多返回点场景下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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:03:18