前言
写代码的时候操作class对象的时候老是出现XXX::operator=(XXX&)...implicitly deleted
的报错,直译过来就是class XXX的copy assignment这个操作被隐式删除,我们解决这个bug需要先了解C++class operator隐式删除的规则
定义
首先给出copy assignment operator隐式删除的规则的定义
A implicitly-declared copy assignment operator for class T
is defined as deleted if any of the following is true:
T
has a user-declared move constructor;T
has a user-declared move assignment operator.
Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class T
is defined as deleted if any of the following is true:
T
has a non-static data member of non-class type (or array thereof) that is const;T
has a non-static data member of a reference type;T
has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);T
is a union-like class, and has a variant member whose corresponding assignment operator is non-trivial.
翻译一下
如果下面任何一个条件为真,则触发copy assignment operator的隐式删除
- 类T有用户定义的移动构造
- 类T有用户定义的移动赋值操作
如果下面任何一个条件为真,则将默认copy assignment operato定义为delete
-
class T有一个数据成员是非static且为const的non-class type
-
class T有一个数据成员是非静态的引用类型
-
class T有一个不能被copy-assigned的类型或者class T的基类不能被copy-assigned
-
class T是一个union类似的class,并且还有多个成员,这些成员对应的assignment operator是non-trivial的
就是union类型,在c++中union也有构造函数…
trivial和non-trivial之前在博客中写过,trivial指的是member function非常"straightforward",没有任何的隐式init操作,比如class a有虚函数或者有一个基类,那么代表他的构造函数是non-trivial的,因为基类和虚函数在构造的时候有一个隐式init操作(虚表,虚指针等操作)
插个3题外话,如果我们的union中有成员,该成员有non-trivial constract function,那么这个union就会报错,因为non-trivial代表有隐式操作,而union是多个成员共用空间,当一个成员被初始化后别的成员都是invalid value,比如union里面有std::string和std::vector等这种带有non-trivial的class#include <iostream> #include <string> union test{ test(){} ~test(){} std::string s; int a; }; int main(){ test t; t.s = "123456"; }
上述代码会报错,但是我们还是用类似的功能怎么办?使用
std::variant
,比如#include <iostream> #include <string> #include <variant> #include <vector> #include <unordered_map> int main(){ std::variant<int, std::string, std::vector<int>, std::unordered_map<int, std::string>> data; std::unordered_map<int, std::string> m; m.insert(std::make_pair(1,"aaaaa")); data = m; std::cout << std::get<std::unordered_map<int, std::string>>(data)[1] << std::endl; }