Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Passing arguments by reference to constructors of self-defined objects

I have read the sometimes it is better to pass arguments by reference so that if the argument type is large in space, we will not copy it (as happens when we pass by reference).

But I dont quite see how it prevents all of the copies. For example consider the BinaryNode class:

template <class T>
class BinaryNode
{
    public:
    //|-------------------- Constructors --------------------
        BinaryNode(const T& _key):key(_key), left(NULL), right(NULL), parent(NULL){}
    protected:
        T key;
        BinaryNode* left;
        BinaryNode* right;
        BinaryNode* parent;
};

When we declare of new BinaryNode, an element T key is created, and even though we pass by reference the argument, still the copy operator = is being activated and still we got ourselves a copy.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

So, is there a way to prevent it? or maybe it is not really a bad thing?

Thanks in advance.

>Solution :

If you used

BinaryNode(T _key):key(_key), left(NULL), right(NULL), parent(NULL){}

, then there would be potentially two copies if the argument is a lvalue. One copy construction from the constructor argument to the parameter and one from the parameter to the member.

You would usually avoid copies by preferring move operations instead. For this you can overload for lvalues which need to be copied and rvalues which can be moved:

 BinaryNode(const T& _key):key(_key), left(NULL), right(NULL), parent(NULL){}
 BinaryNode(T&& _key):key(std::move(_key)), left(NULL), right(NULL), parent(NULL){}

which makes a single copy construction if necessary (if the argument to the constructor is a lvalue) and otherwise makes a single move construction via the second overload.

Or with a minimal penalty that usually shouldn’t matter you can use a single overload:

BinaryNode(T _key):key(std::move(_key)), left(NULL), right(NULL), parent(NULL){}

which will potentially do one move construction or copy construction to the parameter, depending on whether the constructor argument is a lvalue or rvalue, and whether or not the object is directly constructed in the argument, and one additional move construction to construct the member.


Note that in none of this the assignment operator operator= is used. Only constructors are called.


If the argument to the constructor is a lvalue, then a copy construction cannot be avoided, otherwise a move construction cannot be avoided.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading