Well, that's a weird name, =_=.
OK, the following into the topic, in order to demonstrate convenience, the code only write a brief section.
copy Constructor
class Base{public: Base() {} Base(const Base& ) { cout<<"Base copy "<<endl; }};classDerivedpublic Base{public: Derived() {} Derived(constDerived& ind) {}};
Focus on the copy constructor.
Although there is no data in the class-but we said, to demonstrate convenience-now assume that the base class has correctly written its own variable copy.
When you have the following code:
Derived d; Derived s(d);
We want it to behave as if it would output
Base Copy
Of course, when the derived class copy construct occurs, we also want the copy construct of its base class to run correctly.
Then the real behavior is that there is no output.
Because, when we have to write a copy constructor for the derived class, we must carefully copy the elements of the base class [1].
The correct writing should be:
public Base{public: Derived() {} Derived(const//在这里调用base class 的构造函数};
Another class member function associated with replication is operator=.
operator= operator
In the above, it has been pointed out that when we have to write the copy constructor ourselves, we should carefully copy the object.
The same is true when you write the operator= operator, and the code is given directly below:
Class base{ Public:Base() {} Base (Constbase&) {cout<<"Base copy"<<endl; } base&operator= (Constbase&)//Make operator = return a reference to itself is a good practice //Why? Check the information yourself:){cout<<"Base ="<<endl;return* This; }};class Derived: Publicbase{ Public:Derived() {} Derived (Constderived& Ind): Base (Ind) {} derived&operator= (Constderived& Ind) {Base::operator= (IND);//!! This can't be missed!! return* This; }};
* The output in the class is just to better see the behavior of the class, only for demonstration purposes, and it doesn't really make sense.
Do you see the red Note, please don't miss out.
Perhaps you have doubts, it will not be written every time for derived class, you have to write the copy constructor and operator = operator, even if the compiler provides a default version is sufficient to meet our needs?
Don't worry, the compiler will handle it correctly, so you can try it yourself:)
However, the case of operator = is a bit more complicated, pay attention to handling self-assignment in operator =.
Now let's take a single class as an example and give it a pointer to a resource. Well............ It's almost like this:
struct t{int i;}; class base{t* p; Base (const base&); public : Base () {p = new t{3 }; } ~base () {delete p; } base& operator = (const base& inb) { delete p; p = new T (*INB.P); return *this ; } void print () //this function is to verify the result {cout <<p->i<<endl; }};
OK, now there's code that uses them:
Base b1; Base b2; b2 = b1; b2 = b2;//注意这句 b2.print
Although the class of writing doesn't make sense, we expect it to output 3 if we look at it in single use.
But the real behavior is: 0.
The reason is that the self-assignment is not handled correctly in operator =.
When there is b2 = b2
such a statement (see note below)
operator = (const Base& inb) { delete p; //此时inb == *this, delete p 的时候,其实也删除了自身的资源 //那么后面的行为就是不确定的了 new T(*inb.p); return *this; }
Oddly, the operation was not an error, the program as always, cheerfully run, although unpredictable behavior.
Then deal with this problem by adding self-certification to the test:
operator = (const Base& inb) { if(this == &inb) return *this//自我证同测试 delete p; new T(*inb.p); return *this; }
So what's the price?
A control branch was introduced.
The question is, how much will the probability of self-assignment occur?
If you have to make a judgment every time, it will inevitably affect the efficiency.
So the wise man thought of the second approach:copy and swap technology
operator = (const Base& inb) { new T(*inb.p); delete p; p = temp; return *this; }
A copy is constructed first, and then the pointer value is exchanged.
Even self-assignment does not affect the correct behavior.
If you are concerned, when self-assignment, first construct a copy of their own, and then give back to yourself, will not superfluous?
You think about the probability of self-assignment, and then consider whether it's worth it:)
[References]
[1] Scott Meyers, Houtie. Effective C + +: 55 Effective practices for improving program technology and design thinking [M]. Electronic industry Press, 2011.
(clause 11: Handling "self-assignment" in operator=;
Article 12: Do not forget every ingredient when copying an object
Copy object--oeprator= with copy constructor correctly