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);
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 2 years ago.
I was trying to understand the copy constructor, and read this (https://www.tutorialspoint.com/cplusplus/cpp_copy_constructor.htm) tutorialspoint article about it. However, I'm having trouble understanding when the copy constructor was called in the code below. Doesn't Line line(10) only call the Simple constructor, which then allocates memory for ptr and sets the value at ptr to 10?
Is it because we passed line as an argument to display? So does passing an object as an argument always invoke the copy constructor?
#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;
}
Which prints out:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Doesn't Line line(10) only call the Simple constructor
Yes.
Is it because we passed line as an argument to display?
Yes.
So does passing an object as an argument always invoke the copy constructor?
Not necessarily. For example, some types don't have constructors so copying them won't invoke a constructor. Furthermore, if you pass an rvalue, then move constructor may be invoked instead. Or if the type of the argument is different from the type of the parameter, then a converting constructor or conversion operator may be invoked.
If the parameter is a reference (of same type, so no conversion is involved), then no constructor is invoked.
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 found this piece of code on the net:
#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 of executing this code was:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
I can't understand why copy constructor is called when there is no object that is passed as an argument to copy constructor?
also, while debugging, I understand that a destructor is called after function main finished. why it is called and why it is called after function main terminated??
thanks,
void display(Line obj) {
This function takes its parameter by value. This means that passing this parameter to this function will copy it. This is where your copy constructor gets called, when main() calls display().
If you change this function so that it takes its parameter by reference:
void display(Line &obj) {
You will find that the copy constructor no longer gets called, from your sample program.
You will find more information about passing parameters by value versus reference in your C++ book.
The function display takes it's argument by value, hence the copy constructor is called. If that is not wanted, pass it by reference - Line & obj. Better yet, call it by const reference - const Line & obj. But in the latter case, the member function you call inside of display would have to be const also.
The argument in display():
void display(Line obj)
Invokes the copy constructor, as a new object is being made in the argument of the function. Therefore, any object of class Line that you pass to this function will be copied and used as a perameter for the function body.
You invoke this function in the following line:
display(line);
As a result, a copy of line is made in display(). To avoid this, reference an object of class Line instead. Change the way the argument is passed in the function header to:
void display(Line &obj)
This way, you are only referencing the object, hence, not making a copy of it. Therefore, the copy constructor will not be invoked here.
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 am very new to C++ and I don't understand why the copy constructor was called in the following code:
#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;
}
And when it runs:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Why does it construct an other Line object after the first one with the simple constructor?
Thanks!
because you are passing Line as value
void display(Line obj)
{
cout << "Length of line : " << obj.getLength() <<endl;
}
You should pass it as constant reference, which is faster (and display shoud be a constant method so constant objects can call it).
void display(const Line &obj) const
{
cout << "Length of line : " << obj.getLength() <<endl;
}
(provided that you change to int getLength( void ) const;)
And in your case, think of redefining assignment operator
Line &operator=(const Line &other);
or affecting a line in another will copy pointer data and will crash on your second object deletion since memory will be freed twice.
If you want to make sure that default copy constructor / assignment operator cannot be called, just declare them in your private part:
private:
Line &operator=(const Line &other);
Line(const Line &other);
code trying to use them won't compile.
Your display function takes a Line by value - meaning the function gets its own copy. If you don't want that, pass by (const) reference or pointer instead.
The answer is here:
void display(Line obj) { ...
The argument of the function obj is passed by value.
So when the function is called a copy of the argument passed by the caller function is done.
In order to give you a trivial explanation, imagine:
function:main (caller) ->
make a copy of line ->
call the function display (callee) which is going to use the copy made by caller.
That policy is used in various case, for example:
To be sure that the callee function will does any effect (side-effect) on the variables of the caller.
When the callee function will perform a copy of the object, so you can avoid to make a copy inside the body function.
Because passing an argument by value will perform a copy of the argument itself, it is preferable using argument passed by reference.
This is an example:
void display(Line& obj) { ...
In that case it will not performed a copy of the object but the argument obj will be a reference (like a pointer) to the argument passed by the caller function.
In conclusion, passing by reference allows to callee function side effect, in other words the callee function can modify variables "owned" by caller function.
Copy constructors are called in following cases:
(a) when a function returns an object of that
class by value
(b) when the object of that class is passed by
value as an argument to a function
(c) when you construct an object based on another
object of the same class
(d) When compiler generates a temporary object and is initialized with a class object.
And in your code you are passing the object of that clas by value as an argument to a function
Hope this Helps