当前位置:网站首页>3. Disabling copy construction
3. Disabling copy construction
2022-07-01 06:33:00 【HUSTER593】
List of articles
About C++ Copy constructor for , A lot of suggestions are to disable it directly . Why do you suggest that ? What are the limitations of not having a copy constructor ? How to disable copy construction ? This article makes a simple summary of these problems .
The problem discussed here takes the copy constructor as an example , But usually the assignment operator is implemented by copying the constructor Of ( copy-and-swap technology , See 《Exceptional C++》 A Book ), So the discussion here also applies to Fu Value operators , In general, when you disable the copy constructor, you also disable the assignment operator .
1 Why disable copy constructors
Why copy constructors are disabled , There are two main reasons I understand at present . The first is shallow copy , second The second is base class copy .
1.1 Shallow copy problem
The constructor generated by the compiler by default , yes memberwise Copy ( That is, copy the member variables one by one ), For the definition of the following class :
class Widget {
public:
Widget(const std::string &name) : name_(name), buf_(new char[10]) {
}
~Widget() {
delete buf_; }
private:
std::string name_;
char *buf_;
};
The default generated copy constructor , It will be copied directly buf_ Value , It leads to two problems Widget Object points to the same buffer , This can lead to the problem of deleting the same area twice during the deconstruction ( This problem is also called Double kill problem ).
There are many ways to solve this problem :
Write your own copy constructor , Then create a new... In the copy constructor
buf_, However, the copy constructor needs to consider the issue of exception security , So it's very difficult to write .Use
shared_ptrSuch a smart pointer , Let allWidgetObjects share a piece ofbuf_, and Give Wayshared_ptrThe reference counting mechanism helps you handle the deletion problem intelligently .Disable copy constructors and assignment operators . If you're not going to let
WidgetSupport copy , You can totally To disable both operations directly , thus , None of the problems mentioned above are problems .
1.2 Base class copy construction problem
If we don't write our own copy constructors , The compiler will automatically call the copy constructor of the base class to complete the copy of the base class :
class Base {
public:
Base() {
cout << "Base Default Constructor" << endl; }
Base(const Base &) {
cout << "Base Copy Constructor" << endl; }
};
class Drived : public Base {
public:
Drived() {
cout << "Drived Default Constructor" << endl; }
};
int main(void) {
Drived d1;
Drived d2(d1);
}
The output of the above code is as follows :
Base Default Constructor
Drived Default Constructor
Base Copy Constructor // Automatically called the copy constructor of the base class
But if we write for some reason , I wrote the copy constructor ( For example, because of the shallowness mentioned above Copy problem ), The compiler won't help us insert the copy constructor of the base class , It will only help us when necessary The default constructor of the base class :
class Base {
public:
Base() {
cout << "Base Default Constructor" << endl; }
Base(const Base &) {
cout << "Base Copy Constructor" << endl; }
};
class Drived : public Base {
public:
Drived() {
cout << "Drived Default Constructor" << endl; }
Drived(const Drived& d) {
cout << "Drived Copy Constructor" << endl;
}
};
int main(void) {
Drived d1;
Drived d2(d1);
}
The output of the above code is as follows :
Base Default Constructor
Drived Default Constructor
Base Default Constructor // Called the default constructor of the base class
Drived Copy Constructor
This is certainly not the result we want to see , In order to get the right results , We need to manually call the base class ourselves Copy the base class object .
Drived(const Drived& d) : Base(d) {
cout << "Drived Copy Constructor" << endl;
}
It wasn't a problem , It's just that some people forget that when they write copy constructors , Therefore, the sub objects of the base class are not copied normally , It's hard to detect BUG. So in order to solve these egg pain problems once and for all , Simply disable the copy construction and assignment operators .
2 There is no limit to copy construction
stay C++11 Before the object can be put into the container, it must have normal copy semantics , Objects with copy construction disabled cannot be placed directly into containers , Of course, you can use pointers to circumvent this , But you're in the dilemma of managing your own pointer ( Perhaps the use of smart pointers can alleviate this problem ).
C++11 There is mobile semantics in , You can put data in a container by moving it instead of copying it .
Another application of copy constructors is in design patterns Archetypal model , stay C++ There is no copy constructor in , this It may be difficult to implement these two patterns .
3 How to disable copy construction
If your compiler supports C++11, Use it directly
deleteOtherwise, you can declare the copy constructor and assignment operator as
privateNo implementation is provided at the same time .You can encapsulate the second step with a base class , Because the copy constructor generated by default will automatically call the copy of the base class Be , If the copy constructor of the base class is
private, So it can't access , It can't be normal Generate copy constructor .
class NonCopyable {
protected:
~NonCopyable() {
} // About why the statement became protected, Reference resources
// 《Exceptional C++ Style》
private:
NonCopyable(const NonCopyable&);
}
class Widget : private NonCopyable {
// On why to use private Inherit
// Reference resources 《Effective C++》 The third edition
}
Widget widget(Widget()); // error
It's not going to generate memberwise Copy constructor for , For details, please refer to 《 Depth exploration C++ The object model 》 One book .
4 summary
There are two main reasons for the ban :
- Shallow copy problem , That's the secondary decomposition mentioned above .
- Custom copy constructors for base and derived classes , But when a derived class object is copied , Called a copy of the derived class , Instead of calling the custom base class copy, call the default base class copy . This can cause insecurity , For example, in the case of secondary deconstruction , Because we won't call our custom base class deep copy , Or the default shallow copy .
5 appendix
Effective C++ Clause 6 Regulations , If you don't want to use functions generated automatically by the compiler , We should definitely refuse . There are three ways :
- C++11 Add... To the function declaration
deletekeyword :Base(const Base& obj) = delete;, There doesn't have to be a function body , When you call the copy construct again, you will report an error and try to refer to the deleted function . - The easiest way is to declare the copy constructor as
private - Clause 6 A better way to deal with it is given : Create a base class , Declare the copy constructor , But access rights are
private, All classes used inherit from this base class . The default copy constructor will automatically call the copy constructor of the base class , And the copy constructor of the base class isprivate, So it can't access , The copy constructor cannot be generated normally .
Qt That's what it does ,QObject There is a paragraph in the definition , All three are used :
The first method : The easiest way is to declare the copy constructor as private:
private:
Q_DISABLE_COPY(QMainWindow)
#define Q_DISABLE_COPY(Class) \ Class(const Class &) Q_DECL_EQ_DELETE;\ Class &operator=(const Class &) Q_DECL_EQ_DELETE;
The non - copyability of a class can be inherited , For example, those who inherit from QObject You can't use copy constructors or assignment operators on any of the classes .
The second method Inherit one uncopyable class
C++ Before the link , If we can solve this problem at compile time , It will save a lot of time , To solve the problem at compile time , You need to make some bug. We declare a base class that specifically blocks copying uncopyable.
class uncopyable{
protected:
uncopyable(){
}
~uncopyable(){
}
private:
uncopyable(const uncopyable&);
uncopyable& operator=(const uncopyable&);
}
Next , Our class just needs to inherit uncopyable, If a copy is going to happen , The compiler will try to call the copy constructor or assignment operator of the base class , But because the two are private , There will be compilation errors .
边栏推荐
猜你喜欢

How does the port scanning tool help enterprises?
![[ManageEngine] how to realize network automatic operation and maintenance](/img/8a/75332d3180f92c6a6482d881032bbf.png)
[ManageEngine] how to realize network automatic operation and maintenance

C语言课设工资管理系统(大作业)

C language course set up salary management system (big homework)
![[unity shader ablation effect _ case sharing]](/img/e3/464f1cf426e8c03ce3d538ed9cf4bc.png)
[unity shader ablation effect _ case sharing]

C language course set up student elective course system (big homework)

C语言课设学生考勤系统(大作业)
![[postgraduate entrance examination advanced mathematics Wu Zhongxiang +880 version for personal use] advanced mathematics Chapter II Basic Stage mind map](/img/c0/299a406efea51f24b1701b66adc1e3.png)
[postgraduate entrance examination advanced mathematics Wu Zhongxiang +880 version for personal use] advanced mathematics Chapter II Basic Stage mind map

To sort out the anomaly detection methods, just read this article!
![[wechat applet low code development] second, resolve the code composition of the applet in practice](/img/ab/28ab01db84b1437220e659118b2871.png)
[wechat applet low code development] second, resolve the code composition of the applet in practice
随机推荐
SQL语言的学习记录一
Find the original array for the inverse logarithm
Interview questions for HW (OD) post
常用快捷键
DML statement in SQL (data operation language)
[ManageEngine Zhuohao] helps Huangshi Aikang hospital realize intelligent batch network equipment configuration management
[leetcode] day91- duplicate elements exist
HW(OD)岗面试题
软件工程复习
三说 拷贝构造之禁用
嵌入式系统
RestTemplate使用
考研目录链接
[ManageEngine Zhuohao] the role of LAN monitoring
Application of IT service management (ITSM) in Higher Education
MySQL learning
Record MySQL troubleshooting caused by disk sector damage
async 与 await
【微信小程序】如何搭积木式开发?
Camouflage request header Library: Anti useragent