C++显式默认拷贝/移动赋值运算符隐式删除报错原因及修复
报错触发原因
核心问题出在类里的const string theSeparators成员:
- 用
const修饰的成员变量只能在对象构造的时候初始化,对象整个存活周期里根本不允许重新赋值。 - 你写了
=default想让编译器自动生成拷贝赋值、移动赋值运算符,但编译器自动生成的赋值逻辑本质是挨个给当前对象的成员赋新值,碰到不能改的const成员时根本生成不了合法的赋值代码,就会报你看到的「拷贝/移动赋值运算符被隐式删除」的错误。
另外你代码里还藏了个会触发编译报错的问题:头文件里构造函数声明已经给separators参数设了默认值"\t\n",cpp实现文件里不能再给同一个参数重复写默认值,不然编译器会报重复指定默认参数的错。
修复方案
根据你实际想要的语义选一种改就行:
- 如果你就是要
theSeparators在对象创建完之后不能改:直接把两个默认赋值运算符显式标成删除就可以——本来类里有不可修改的const成员时,给已经存在的对象做赋值就是语义矛盾的操作。改完之后类里的赋值运算符声明长这样:
注意选这种方案的话,你必须在构造函数的初始化列表里给Dictionary& operator=(const Dictionary&) = delete; Dictionary& operator=(Dictionary&&) = delete;theSeparators和filename赋初值,不能在构造函数的函数体里给这两个成员赋值,正确的构造函数写法参考:// 头文件声明保留默认参数即可,cpp里不要重复写 Dictionary::Dictionary(const string& filename, const string& separators) :filename(filename), theSeparators(separators) { /* 其余业务逻辑 */ } - 如果你需要Dictionary类支持两个对象之间互相赋值:直接把
theSeparators前面的const删掉就行。这个成员本身是private的,类外面的代码根本没权限直接改它,只要你自己不在类的内部逻辑里乱改,完全能保证它不会被意外修改,同时编译器也能正常生成赋值运算符。选这个方案同样记得把cpp实现里构造函数参数后面重复写的= "\t\n"删掉。
内容的提问来源于stack exchange,提问作者Coder-Me
相关产品推荐
相关产品推荐

