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

如何创建由不可拷贝对象组成的std::tuple?

无需修改对象类构造包含不可拷贝元素的std::tuple

问题原因分析

原代码编译失败的核心原因是:
当你用a_b_{A(w,x), A(y,z)}初始化std::tuple<A, A>时,会先创建两个临时的A对象,随后std::tuple会尝试通过拷贝构造来初始化内部的A实例。但A的拷贝构造函数已被显式删除,因此触发编译错误。

解决方案(无需修改struct A)

方案1:使用std::piecewise_construct分块构造(C++11及以上兼容)

利用std::piecewise_construct标记,配合std::forward_as_tuple传递每个A的构造参数,让std::tuple直接在自身内存空间内构造A对象,全程避免拷贝操作。

修改后的完整代码:

#include <tuple>
#include <iostream>
#include <utility>

struct A {
    int& x;
    int& y;

    A(int& a, int& b) : x(a), y(b) {}
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};

class B {
public:
    B(int& w, int& x, int& y, int& z)
    : a_b_(std::piecewise_construct,
           std::forward_as_tuple(w, x),
           std::forward_as_tuple(y, z)) {}
    
private:
    std::tuple<A, A> a_b_;
};

int main() {
    int w =1, x=2, y=3, z=4;
    B b{w,x,y,z};
    return 0;
}

原理说明:

  • std::piecewise_construct是一个标记对象,告诉std::tuple要按"分块"的方式构造每个元素
  • std::forward_as_tuple(w, x)会将构造参数打包成引用类型的tuple,避免参数拷贝
  • std::tuple直接用每个参数tuple里的值调用A的构造函数,在自身内存中创建A实例,完全跳过临时对象和拷贝步骤

方案2:C++20简化写法(编译器支持时可用)

在C++20中,std::tuple支持直接通过嵌套初始化列表传递构造参数,语法更简洁:

class B {
public:
    B(int& w, int& x, int& y, int& z)
    : a_b_{ {w, x}, {y, z} } {}
    
private:
    std::tuple<A, A> a_b_;
};

这种写法依赖C++20的聚合初始化增强特性,编译器会自动将内部的{w,x}解析为A的构造参数,直接在tuple内部构造A对象,无需拷贝。

内容的提问来源于stack exchange,提问作者mmodel1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:34:57