很多时候,我们并不希望使用编译器默认生成的拷贝复制与拷贝构造函数,我们可以通过以下3种方式禁用拷贝构造与copy assign:
目录
1、设置拷贝构造与copy assign为私有
#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
Base(){};
~Base(){};
private:
Base(const Base &);
Base &operator=(const Base &);
};
int main()
{
Base b1;
Base b2(b1);//不可访问
system("pause");
return 0;
}
报出以下错误:
2、继承不可拷贝构造与拷贝赋值的基类
因为默认生成的拷贝构造函数会自动调用基类的拷 贝构造函数,如果基类的拷贝构造函数是 private
,那么它无法访问,也就无法正常 生成拷贝构造函数。
#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
Base(){};
~Base(){};
private:
Base(const Base &);
Base &operator=(const Base &);
};
class Drivered : private Base//继承不可拷贝与复制基类
{
};
int main()
{
Drivered d1;
Drivered d2 = d1; //拷贝复制
Drivered d3(d1); //拷贝构造
system("pause");
return 0;
}
报错信息如下:
3、使用delete
#include <iostream>
#include <string>
using namespace std;
class Uncopyable
{
public:
Uncopyable(){};
~Uncopyable(){};
Uncopyable(const Uncopyable &) = delete; // 阻止copying
Uncopyable &operator=(const Uncopyable &) = delete;
};
int main()
{
Uncopyable un1;
Uncopyable un2=un1;
system("pause");
return 0;
}
报错信息如下:
这只能在C++11 以及以上使用(注意:c++98不支持),delete 关键字可用于任何函数,不仅仅局限于类成员函数:
bool IsLucky(int number); // original function
bool IsLucky(char) = delete; // reject chars
bool IsLucky(bool) = delete; // reject bools
bool IsLucky(double) = delete; // reject doubles and floats
4、禁用原因
(1)避免浅拷贝,导致双杀问题;
(2)自定义了基类和派生类的拷贝构造函数,但派生类对象拷贝时,调用了派生类的拷贝,没有调用自定义的基类拷贝而是调用默认的基类拷贝。这样可能造成不安全,比如出现二次析构问题时,因为不会调用我们自定义的基类深拷贝,还是默认的浅拷贝。