Question

The rule of three (also known as the Law of The Big Three or The Big Three) is a rule of thumb in C++ that claims that if a class defines one of the following it should probably explicitly define all three: destructor, copy constructor, copy assignment operator.

Why is a non-default constructor not considered as one of them? When there is any resource managed in the class, programmer has to define a non-default constructor anyway.

Was it helpful?

Solution

Why is a non-default constructor not considered as one of them? When there is any resource managed in the class, programmer has to define a non-default constructor anyway.

That is not necessarily true. The constructor might not aquire any resource. Other function(s) might aquire them as well. In fact, there can be many functions (including the constructor(s) themselves) which might aquire resources. For example, in case of std::vector<T>, it is resize() and reserve() which aquire resources. So think of constructor(s) just like other function(s) which might aquire resources.

The idea of this rule is that when you make a copy, the default-copy code generated by the compiler wouldn't work. Hence you need to write the copy-semantic yourself. And since the class manages resources (it doesn't matter which function(s) aquire it), the destructor must release it, because the destructor is guaranteed to be executed, for a fully constructed object. Hence you've to define the destructor as well. And in C++11, you've to implement move-semantics as well. The logical argument for move-semantic is same as that of copy-semantics, except that in move semantic, you changed the source as well. Move-semantic is much like organ-donor; when you give your organ to other, you don't own it anymore.

OTHER TIPS

That's not what the rule of three is about.

Any class that manages resources will have that destructor, and hence the rule of three applies anyway. The point is that you don't absolutely need non-default constructors, but you do need the others (copy constructor / assignment operator).

At least it used to be vital for e.g. elements in standard containers.

Now with move semantics (c++11), things are starting to shift a bit. Will there be a rule of 5? I don't know how it will pan out in terms of 'best practices' and 'rules of thumb'.

In fact one could state a variation of the Rule of Three already: a class that defines a destructor should also define a copy/move constructor and copy/move assignment operator. AND if a copy constructor is defined, a copy assignment operator should also be defined. AND if a move constructor is defined, a move assignment operator should also be defined.

This is going to be my rule of thumb for a while, anyways.

If you aquire any resources (eg with new) you are quite right, but it is assumed that you don't forget to release the resources in the destructor. Once you created the destructor the rule of three kicks in and you should define all three.

However, if for example you only have some member variables in your class that you initialize with copy semantics you don't need the destructor and the rule doesn't apply.

Defining a non-default constructor doesn't automatically mean you need a destructor etc - you may just be using that constructor as a convenience to fill in a POD type.

That said, the same applies to default constructors.

Basically, the "do you need the big three?" is triggered when the class will manage a resource. You still might not need a default constructor, but you do need a constructor to set up a valid initial state.

That newly-constructed state may not own an instance of the resource yet, but if it doesn't, then it must know that it doesn't (e.g. have a null pointer).

However, the big three are also used implicitly in a lot of cases. Temporaries, for example, are default-constructed. One reason you would need a non-default constructor is simply to block the implicit default constructor from being provided and used.

So one reason to define all three at once is to ensure that your code (including that provided implicitly by the compiler) remains sane.

Almost always, if you're managing a resource, you will have a default constructor, so that's why the rule mentions that - but so long as you define some kind of constructor, you should be OK.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top