Why was copy constructor called in this example? - c++

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

Related

Why is the copy constructor called after the simple constructor is called? [duplicate]

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.

C++ copy constructor calling other constructors [duplicate]

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.

is copy constructor called automatically even when there isn't any object to be copied?

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.

How in this copy constructors is called?

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);

Explaining copy constructor example

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.