如何创建由不可拷贝对象组成的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
相关产品推荐
相关产品推荐

