-2

I am reading up on copy constructors and the way they typically receive the parameters as constant references. Why should the copy constructor accept its parameter by reference in C++? I wrote a code snippet to test that when a parameter is received by value, whether a copy is created( as stated in the accepted answer of the provided link). But I don't see the constructor called when an object is received by value. Please explain why? And isn't a copy created when an object is returned by value too? again no constructor called there as well. Why?

class Vector
{
   public:
    Vector(){cout << "Vector constructor"<<endl;}
    ~Vector(){cout << "Vector destructor"<<endl;}

};
Vector use(Vector z)
{
   cout << "At call" << endl; 
  Vector v;
  cout << "after definition" << endl;
  return v;
}
int main()
{
    Vector t;
    cout << "After irrelevant" << endl;
 use(t);
 cout << "After use"<< endl;
}

The output looks as follows:

Vector constructor
After irrelevant
At call
Vector constructor
after definition
Vector destructor
Vector destructor
After use
Vector destructor

Update1: I had missed adding the copy constructor in the initial example. Once that is done the code behaves as expected.

Community
  • 1
  • 1
  • 4
    You have no copy-constructor. The builtin one won't print anything ;) – Karoly Horvath Oct 14 '15 at 13:11
  • 4
    The copy constructor is called when passed by value, not the normal constructor. – owacoder Oct 14 '15 at 13:11
  • My bad, had a lot of other code in the same program..messed it up :) will add and test again – Harish Kulkarni Oct 14 '15 at 13:13
  • "isn't a copy created when an object is returned by value too?" The answer to that one is **maybe**. If you had properly tested a copy constructor, you would find it is called when an object is passed by value. But the compiler may choose to bypass the copy constructor when an object is returned by value. – JSF Oct 14 '15 at 13:16
  • @JSF ok, so compiler optimizes this for us? Then why do we need move constructor which was introduced in C++11? – Harish Kulkarni Oct 14 '15 at 13:18
  • Well, there are many reasons, but I just would like to point out the "may" in that sentence. – Karoly Horvath Oct 14 '15 at 13:22

2 Answers2

3

The default constructor is not called when an object is passed by value, the copy (or move) constructor is.

If we trace the copy constructor like this:

class Vector
{
   public:
    Vector(){cout << "Vector constructor"<<endl;}
    Vector(const Vector&) {cout << "Vector copy constructor"<<endl;}
    ~Vector(){cout << "Vector destructor"<<endl;}
};

Then we see the constructor being called:

Vector constructor
After irrelevant
Vector copy constructor //here
At call
Vector constructor
after definition
Vector destructor
Vector destructor
After use
Vector destructor

There is no copy on the return because the copy is elided by the compiler for efficiency. If you pass -fno-elide-constructors or equivalent to your compiler then you'll see an additional copy.

Community
  • 1
  • 1
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
0

Copy is created to pass the value, so copy constructor is called there.

#include <iostream>
using std::cout;
using std::endl;
class Vector
{
    public:
    Vector(){cout << "Vector constructor"<<endl;}
    Vector(const Vector&){cout << "Vector copy constructor"<<endl;} // add this line
    ~Vector(){cout << "Vector destructor"<<endl;}

};
Vector use(Vector z)
{
     cout << "At call" << endl; 
    Vector v;
    cout << "after definition" << endl;
    return v;
}
int main()
{
    Vector t;
    cout << "After irrelevant" << endl;
    use(t);
    cout << "After use"<< endl;
}

output:

Vector constructor
After irrelevant
Vector copy constructor
At call
Vector constructor
after definition
Vector destructor
Vector destructor
After use
Vector destructor
MikeCAT
  • 73,922
  • 11
  • 45
  • 70