简体   繁体   中英

copy constructor being called multiple times c++

I was going over through tutorials on copy constructor in c++ offered by tutorialspoint.com http://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm

In one of their sample codes:

#include <iostream>

using namespace std;

class Line
{
public:
    int getLength(void);
    Line(int len);          // simple constructor
    Line(const Line &obj);  // copy constructor
    ~Line();                // destructor

private:
    int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
    *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}

int Line::getLength(void)
{
    return *ptr;
}

void display(Line obj)
{
    cout << "Length of line : " << obj.getLength() << endl;
}

// Main function for the program
int main()
{
    Line line1(10);

    Line line2 = line1; // This also calls copy constructor

    display(line1);
    display(line2);

    return 0;
}

and the output was

Normal constructor allocating ptr
Copy constructor allocating ptr.
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Freeing memory!

I don't understand the output. To me it show be that the normal constructor is called for line1, then one copy constructor for line2 and then 2*"freeing memory" for the 2 objects

The output I thought was:

Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Length of line : 10
Freeing memory!
Freeing memory!

q.1> why copy constructor is called multiple times initially

q.2>4 times "freeing memory" and that too one in between, I am really confused, could you help me out.

Thanks

This is simply constructed:

Line line1(10);

and as you recognized, this is where your copy constructor is called:

Line line2 = line1;

So far so good. Now take a look at the signature to display :

void display(Line obj);

This is what we call pass-by-value. Pass-by-value is a parameter form that causes a new object to be constructed from the one passed in. Hence, the two calls here:

display(line1);
display(line2);

are both calling the copy constructors to get line1 and line2 into the function-local obj variable.

This is roughly equivalent to this:

// Instead of calling display, this happens instead:
{ // Entering a new scope
    Line obj = line1;
    cout << "Length of line : " << obj.getLength() << endl;
} // Exiting scope

{ // Entering a new scope
    Line obj = line2;
    cout << "Length of line : " << obj.getLength() << endl;
} // Exiting scope

obj is it's own object now, independent of the lifetimes of line1 or line2 , and when obj goes out of scope, as it does at the end of the function, it's destructor is called. This would explain the four total calls to the destructor: one for the original simply constructed object ( line1 ), one for the copy constructed object ( line2 ), and two for the two function-local obj s.

If you want to avoid a copy like you indicated in your question, use pass-by-reference .

void display(Line obj) calls copy constructor for its parameter,
you may use const reference to avoid the copy ( void display(const Line& obj) ).

The example goes like this:

Line line1(10); // Normal constructor allocating ptr

Line line2 = line1; // Copy constructor allocating ptr

display(line1); /* Copy constructor allocating ptr, because function is this:

void display(Line obj);

This will make a copy of the object going into the method, just as if it were an int, for example. If you want to eliminate this copy, change to

void display(const Line& obj);

which passes a reference. */

/* Next the funtion is called and prints

Length of line : 10

Then the destructor of the copy is called at the end of the function, before it returns.

Freeing memory!

*/

display(line2);/* Next the same pattern is repeated with the second function call:

Copy constructor allocating ptr.

Length of line : 10

Freeing memory! */

return 0; /* Finally, both line1 and line2 are destructed:

Freeing memory!

Freeing memory!

*/

q.1> why copy constructor is called multiple times initially

You call display(line) , display(line2) . void display(Line obj) is defined to receive as a parameter Line object, so every time you call for display , the object is copied for that function (like if you were sending integer to a function, its value would be copied so that if the function modified that integer it wouldn't effect anything but the scope of the function). In order to reduce the number of copy constructors you can define display as void display(Line& obj) . But then pay attention that every modification made on obj will be reflected in the main() .

q.2>4 times "freeing memory" and that too one in between, I am really confused, could you help me out.

Two times as you expected (one for line and another for line2 ) and two more for the object which was copied to display function. Once the flow of display is executed, it destructs all the local objects and function parameter is considered to be a local object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM