C++带初始化列表的结构体赋值:已删移动赋值运算符报错疑问
关于删除移动赋值后初始化列表赋值报错的问题解答
咱们先把你的代码场景摆出来,方便梳理问题:
首先是定义的结构体:
struct Data { int a,b; Data& operator=(Data &&other) = delete; };
然后触发编译错误的赋值操作:
Data A[2]; A[0] = {1, 2};
为什么会触发“调用已删除函数”的错误?
核心原因要分两步拆解:
初始化列表如何关联到右值引用
当你写A[0] = {1,2}时,这个初始化列表{1,2}并不会直接变成右值引用——而是编译器会用它临时构造一个Data类型的对象。这个临时对象没有名字,生命周期仅限于当前赋值表达式,属于C++里的纯右值(prvalue),而纯右值会被优先匹配到Data&&类型的参数上,也就是你删除的那个移动赋值运算符的参数类型。为什么不能用拷贝赋值代替?
这里有个容易忽略的C++规则:如果你显式声明了移动赋值运算符(哪怕是用= delete删除它),编译器就不会再自动生成默认的拷贝赋值运算符了。所以此时你的Data类既没有可用的移动赋值(被删了),也没有拷贝赋值(编译器没生成),自然找不到合适的赋值运算符来完成A[0] = 临时对象的操作,编译就报错了。
补充验证:让代码编译通过的方法
如果你想让这段代码正常运行,可以显式定义拷贝赋值运算符,比如:
struct Data { int a,b; Data& operator=(Data &&other) = delete; Data& operator=(const Data& other) { a = other.a; b = other.b; return *this; } };
这样编译器就会用拷贝赋值来接收那个临时的Data对象(因为右值可以绑定到const Data&),代码就能正常编译运行了。
内容的提问来源于stack exchange,提问作者V K
相关产品推荐
相关产品推荐

