so i'm new to C++ (with java as a background) and i was going through copy constructor and destructor section but i still don't get it. The example i will show you is taken from tutorialpoints.com. So i have this code but the output just confuses me.
#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 1***************************
Line line2 = line1; // This also calls copy constructor
display(line1);
display(line2);
return 0;
}
Output
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!
So in line 1 (Main), why does it also call the copy constructor when it has its own argument?
Also after the first call to the method display why is there another call to the copy constructor ?
this is the input i would have expected
`Normal constructor allocating ptr //Because Line one has its argument
Copy constructor allocating ptr. //Because Line2 is a copy of Line1
Length of line : 10
Freeing memory! // Call to destructor after Line1 is desplayed
// Memory leak Since Line2 is now pointing to nothing, i guess is what we call `shallow pointers?!`
Sorry if it was too long, hopefully i was clear. PS i'm Only familiar with regular pointers!
What's confusing you is that display takes a Line by value. When you pass a Line to the display function, it copies it (calls copy ctor) into its local argument and when the display function ends, that local argument goes out of scope and the copied Line destructs.
int main( )
{
Line line1(10); // calls ctor that takes an int
Line line2 = line1; // calls copy ctor
display(line1); // calls copy ctor, prints, and then destructs the copy
display(line2); // calls copy ctor, prints, and then destructs the copy
return 0;
} // line 2 goes out of scope and destructs, then line 1 does the same
The compiler emits code that automatically calls the destructor when an object is explicitly destroyed (e.g. delete on an object created with operator new) or reaches the end of its defined life (e.g. a temporary destroyed when no longer needed, a declared variable passing out of scope).
In your code (as you have it at the time of my writing this) the sequence of events is
line1 is constructed
line2 is constructed as a copy of line1
line1 is passed by value to display(). This creates a temporary
copy of line1. When display() returns, the destructor is invoked for the temporary.
line2 is passed by value to display(). This creates a temporary
copy of line2. When display() returns, the destructor is invoked
for the temporary.
main() returns.
line1 and line2 are destructed in reverse order of their
construction, and destructor invoked for each.
So in line 1 (Main), why does it also call the copy constructor when
it has its own argument?
It will not call copy constructor, comment your code in main and try.
live_demo: http://coliru.stacked-crooked.com/a/64ad2d47a7ee953b
Also after the first call to the method display why is there another
call to the copy constructor ?
void display(Line obj)
When you invoke this function since your passing argument by value system creates a local copy of object named obj to function, it is happening using copy constructor of your class. This local objects scope will end as soon execution completes the scope of your function display.
Here is each part of main along with what it prints.
Line line1(10); //Line 1***************************
Normal constructor allocating ptr
Line line2 = line1; // This also calls copy constructor
Copy constructor allocating ptr.
display(line1);
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
display(line2);
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
return 0;
}
Freeing memory!
Freeing memory!
You are passing in Line by value so it copies the Line you have, calls the function and then the end of that function deletes the Line it got.
Related
This question already has answers here:
Why is the copy constructor called when we pass an object as an argument by value to a method?
(3 answers)
Closed 4 years ago.
I have this code. I'm not that proficient in C++, so I'm going to ask several questions:
#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;
cout<<&obj<<endl;
*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() {
int a = 10;
cout<<&a<<endl;
Line line(a);
display(line);
return 0;
}
Here I don't see where we call copy contructor.
Destructor is being called twice. Where is the second object is being created?
Line::Line(const Line &obj) receives address of a as a parameter? I guess not. But why? a by itself is not an instance of Line, so why function accepts that?
What would be the difference between Line::Line(const Line &obj) and Line::Line(const Line obj)
And could you please explain this *ptr = *obj.ptr; . From here i know only lhs, which dereferences ptr (aka sets value of an object). But I didn't get what's in rhs?
I'd appreciate if you explain with less technical terms and more examples, for clarity
Above code outputs this:
0x7fff692196a4
Normal constructor allocating ptr
Copy constructor allocating ptr.
0x7fff69219698
Length of line : 10
Freeing memory!
Freeing memory!
Here for some reason default constructor is called. I don't see any place where we create object without parameter (aka that goes to default constructor)
I don't see any place either! How can you be so sure the default constructor is called? In fact, your class is not constructible using a default constructor because there isn't one. If you try this:
Line l;
It won't compile since there is no default constructor.
Destructor is being called twice. Where is the second object is being created?
It this line:
display(line);
You function receives a value. To have a value both in your main and your display function, you have to copy it somehow. Passing line will copy it from your main to your function.
Line::Line(const Line &obj) receives address of a as a parameter? I guess not. But why? a by itself is not an instance of Line, so why function accepts that?
No. This is a reference. The copy constructor receive a reference from other context to copy it.
What would be the difference between Line::Line(const Line &obj) and Line::Line(const Line obj)
One is a reference, the other is passing by value (a copy, move or other construction). If the copy constructor had to receive a value, how would you copy the value into the copy constructor? The copy constructor must receive a reference.
And could you please explain this *ptr = *obj.ptr; . From here i know only lhs, which dereferences ptr (aka sets value of an object). But I didn't get what's in rhs?
I don't know what you mean by rhs and lhs, is not in the code you posted. But indeed, *ptr = *obj.ptr will set the value from the integer pointed by obj.ptr into the variable pointed by this->ptr.
I recommend getting a good C++ book and follow a tutorial that will teach you the basics.
I was trying to understand the basics of copy constructors and came across the following example.
#include <iostream>
using namespace std;
class Line
{
public:
int getLength() const;
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()
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength() const
{
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;
}
When executed, it gives the following output.
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!
The copy constructor is called only once, in the Line line2 = line1; But it seems that the copy constructor is being called twice. So I commented out the
display(line1); and display(line2); . After that the output is something like this.
Normal constructor allocating ptr
Copy constructor allocating ptr.
Freeing memory!
Freeing memory!
So the problem(I don't know if I should call it a problem or its a default standard in C++) is with the display function. Could it be because the display() function automatically creates a copy of the object its processing and that's why the copy constructor is called twice for each instance? Kindly clarify. Thanks.
with void display(Line obj), you pass object by value, so create copy.
You should pass by (const) reference to avoid the copies:
void display(const Line& obj)
Could it be because the display() function automatically creates a copy of the object its processing and that's why the copy constructor is called twice for each instance? Kindly clarify. Thanks.
That is exactly what is happening. If you pass an object into a function by value, it will be copied prior to the function call executing. If you do not wish this to happen, use a pointer or a reference.
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 objs.
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.
I am reading copy constructors for the first time. Here is the link from which I am reading it: http://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm
Now, in their first example, in the output, they have written this:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
I just want to know, how exactly the copy constructor is getting called here? In the main function, they have written it as:
#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 line(10);
display(line);
return 0;
}
So, it's just Line line(10) which will call the constructor for setting length. Why exactly will the copy constructor be called? Wont' the constructor be called when we pass it an actual object of class Line?
You are passing line by value to display.
When you pass an object to a function by value, a copy of the object is created on the stack. In your case, the obj parameter of the display function is created calling the copy constructor of the class Line.
When you passed solid object as display(Line) function parameter, copy constructor is called because in C++ arguments are passed by value when you pass solid object. So when you passed Line object into function, copy constructor is called to create object copy from existing one. To avoid copying you need to pass parameters by reference or pointer(smart or normal).
display is defined like:
void display(Line obj)
This is pass by value and not pass by reference. A copy must be made which is why the copy constructor is called.
Your function display is defined like:
void display(Line obj)
This is a call-by-value, and in the case of call-by-valuethe copy of the argument is made, not the actual object is passed. Hence when your function is called copy constructoris invoked.
If you want to avoid it, pass parameter by reference or pointer.
Change the definition of Display from void display(Line obj) to
void display(Line *obj)
and in mainchange the function call from display(line); to display(&line);
A copy constructor is used for many things such as when I need to use pointers or dynamically allocate memory for an object. But looking at this example at tutorialpoint.com:
#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 line(10);
display(line);
return 0;
}
the result is :
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
and when I commented out (the copy constructor) and the code inside destructor I got the same results:
Normal constructor allocating ptr
Length of line : 10
So what is the difference between using the copy constructor here or not? Also why does "Freeing Memory!" occur twice?
The argument to the display() function is passed by value, so the compiler calls the copy constructor to create it. When the class defines its copy constructor you get the correct semantics: the copy constructor makes a copy, and that copy has its own memory to hold the length. When you remove the copy constructor, the compiler generates one for you, and the copy that gets passed to display() has the same pointer as the original. When that copy gets destroyed it deletes the memory that ptr points to. When the original gets destroyed it deletes the same memory again (which happens to have no visible effects here). That's definitely not what you want to have happen, which is why you need to define a copy constructor. As #Joe says: inside the destructor, print the value of `ptr' to see this more clearly.
Print the address of the memory being freed.
I believe you will find the compiler generated the constructor for you, did a value copy of the contents, including the pointer, and you are double-freeing the pointer and just getting lucky that the runtime isn't complaining about it.
The compiler generated copy constructor is still being called - nothing has changed in that regard, you just aren't printing anything from it since you didn't write it.
If we don’t define our own copy constructor, the C++ compiler creates a default copy constructor for each class which does a member wise copy between objects. The compiler created copy constructor works fine in general. We need to define our own copy constructor only if an object has pointers or any run time allocation of resource like file handle, a network connection..
A constructor of some type T of the form
T (const & T);
The single argument must be a const reference to an existing object of same type
Creates a duplicate of the existing object
Used whenever a copy of an object is needed
Including arguments to functions, results returned from functions
Problems with pointer-based arrays in C++:–
No range checking.
Cannot be compared meaningfully with ==
No array assignment (array names are const pointers).
If array passed to a function, size must be passed as a separate argument.