Copy Constructor - c++

I am new to C++ programming, I got a doubt when I was reading a C++ regarding copy constructor. Why copy constructor will call when we pass object of class to a outside function as pass by value. Please go through my code as below.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
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;
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)//here function receiving object as pass by value
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main( )
{
Line line(10);
display(line);//here i am calling outside function
_getch();
return 0;
}
In the above the I am passing object of class as parameter and display function receiving it as pass by value. My doubt is when I pass object to a function which is not a member of class why copy constructor is calling. if I receive object as reference in display() function[i.e display(Line &Obj)] it is not calling the copy constructor. Please help me what is the difference.

When you pass something by value, the copy constructor is used to initialize the parameter that's passed -- i.e., what's passed is a copy of whatever you give, so of course the copy constructor is used to create that copy.
If you don't want the value copied, pass by (probably const) reference instead.

Related

Multiple calling constructor will change the member pointer address in C++

I write a program to check the init process of class creation, and found calling the constructor multiple times changed the member pointer address. Look at following snippet.
#include <iostream>
using namespace std;
class FF {
public:
FF(){
this->ptr = NULL;
value = 1;
cout << "ptr address in 1: " << this->ptr <<endl;
}
FF(const int* ptrcopy, const int valuecopy){
cout << "ptr address in 2: " << this->ptr << endl;
FF();
/* Is this equivalent with FF() ?
this->ptr = NULL;
value = 1;
*/
init(ptrcopy, valuecopy);
}
void init(const int* ptrcopy, const int valuecopy) {
cout << "ptr address in 3: " << this->ptr << endl;
if (this->ptr != NULL)
{
cout << "error happened, the address of ptr is " << this->ptr << endl;
return;
}
}
private:
int* ptr;
int value;
};
int main(){
int *ptr = new int(10);
int value = 1;
FF fclass(ptr, value);
delete(ptr);
return 0;
}
The output is
ptr address in 2: 0x400b40
ptr address in 1: 0
ptr address in 3: 0x400b40
error happened, the address of ptr is 0x400b40
It seems the calling of FF() only init the ptr to NULL in its space, and the ptr change back to original 0x400b40 after calling.
Can someone explain about it ?
Your call of FF(); will create a new, unnamed stack based FF object, construct it (generating the output you see), then immediately destroy it again (for which you don't show any output). This is why the ptr address seems to change back - because it never changed. Add in a destructor that prints out the address of this to see this occur.
Incidentally, your use of this->ptr in the second (parameterized) constructor is Undefined Behavior because you never assign a value to ptr.
If your intent is to call the default constructor from the parameterized constructor, and your compiler supports C++11, you can delegate to the default constructor.
FF(const int* ptrcopy, const int valuecopy): FF() { /* ... */ }
I think what's happening is that in constructor 2 you are printing the uninitialized value for ptr (0x400b40) and then you are creating a new object of type FF with FF(). Then constructor 1 will be called for the new object, it's ptr member will be changed to NULL (so when printed it will be 0). After the constructor for the new object finishes it returns to constructor 2 (the destructor for the previously object is called) and then you call init which will display the same value for ptr as before since this object's ptr member hasn't been changed.
It might help you to also print the something in the destructor. That would be FF::~FF().
EDIT: Spelling and destructor suggestion
Like 1201ProgramAlarm said, doing FF(); does not call the constructor of the current object. To do so, you would do something like below (assuming C++11):
class FF {
public:
FF() : ptr(nullptr), value(1) {
cout << "ptr address in 1: " << this->ptr <<endl;
}
FF(const int* ptrcopy, const int valuecopy) : FF() {
cout << "ptr address in 2: " << this->ptr << endl;
init(ptrcopy, valuecopy);
}
void init(const int* ptrcopy, const int valuecopy) {
...
}
...
};
See also this question.
Compare to the following:
class C
{
public:
C() { std::cout << 'c' }
~C() { std::cout << 'd' }
};
void test()
{
C f;
std::cout << 't';
}
You should know about already, you create a temporary object running out of scope at the end of the function. You should see output ctd
void test()
{
C();
std::cout << 't';
}
Same again, with a little difference: The object runs out of scope right after the statement is executed, so output would be cdt.
Now exactly the same happens in your constructor, you just create a temporary, separate FF object when calling FF() inside the constructor's body.
I suppose you instead intended constructor delegation (available since C++11); however, syntax is different:
FF(int const*, int)
: FF() // as if using the initialiser list
{ /* can do some extra work here */ }
Now, the default constructor will be called on this before entering the function body. Of course, works with any constructor, as long as called appropriately:
FF() : FF(nullptr, 0) { }
Now, the default constructor would call your second one.

Two cases which should avoid calling copy constructor

I have learned about three cases about calling the copy constructor
1. A variable is being initialized from an object of the same class
2. A function is called with a value parameter of the class
3. A function is returning a value that is an object of the class
Also textbook says for the above two cases(case2 and 3), to avoid calling copy constructors, use call-by-reference
I have searched for some information but I can't understand exactly.
For example(I made my own code)
class CpClass{
int p;
CpClass(const CpClass &obj){
cout<<"user-defined constructor"<<endl;
p = obj.p;
}
~CpClass(){
cout<<"destructor"<<endl;
}
};
void show1(String &s)
{ cout << "show1 : " << s.p; }
void show2(String s)
{ cout << "show2 : " << s.p; }
int main(){
CpClass c1(10);
CpClass c2(c1);
show1(c2);
show2(c2);
};
I found some information about this.
First, When we pass an argument which is a class object, if the parameter is reference form not value, it does not call the destructor as soon as the function is ended. It calls destructor when the main function is ended
Second, it call constructor when copy argument whether the parameter form is call by value or call by reference(In code, String &s or String s)
Am I correct or not?
As your posted code does not compile I changed it to:
#include <iostream>
using namespace std;
struct CpClass{
int p;
CpClass(int i){
cout<<"user-defined constructor"<<endl;
p = i;
}
CpClass(const CpClass &obj){
cout<<"user-defined constructor"<<endl;
p = obj.p;
}
~CpClass(){
cout<<"destructor"<<endl;
}
};
void show1(CpClass &s)
{ cout << "show1 : " << s.p; }
void show2(CpClass s) { // Constructor
cout << "show2 : " << s.p;
} // Destructor for s
int main() {
CpClass c1(10); // Constructor
CpClass c2(c1); // Constructor
show1(c2);
show2(c2);
return 0;
}; // Desctructor for c2, c1
Following lines call a constructor
CpClass c1(10);
CpClass c2(c1);
show2(c2);
The first desctructor is called after leaving function
void show2(CpClass s)
The destructors for c2 and c1 are called when leaving main function (in this order)
CpClass &s is syntactic sugar for CpClass * const s. That means that s contains the address of the object and not a copy. Syntactic sugar means that this is a short form and you don't need to dereference.

why overloaded new operator is calling constructor even I am using malloc inside overloading function?

I am trying to understand overloading new operator. I wrote the code as below.
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class loc
{
int lo, la;
public:
loc()
{
}
loc(int x, int y)
{
cout << "In constructor\n";
lo = x;
la = y;
}
void show()
{
cout << lo << " ";
cout << la << endl;
}
void *operator new(size_t sz);
void operator delete(void *p);
};
void *loc::operator new(size_t sz)
{
cout << "in Overloaded new\n";
void *p = malloc(sz);
return p;
}
void loc::operator delete(void *p)
{
cout << "in Overloaded delete\n";
free(p);
}
int main()
{
loc *p1 = new loc(10, 20);
p1->show();
delete p1;
return 0;
}
I thought it won't call the constructor because I overloaded the new operator with malloc function call inside overloading function. But the output is as below.
in Overloaded new
In constructor
10 20
in Overloaded delete
That means constructor is getting called. How this is possible? Does this mean will malloc() call constructor?
A new expression results in two separate things happening: allocation of the memory needed by the object begin created, and initialization of the object.
The new operator, on the other hand, just handles the allocation part. When you overload the new operator with respect to a specific class, you are replacing the allocation of memory to the object.
This division of functions makes sense when you realize that not all objects are allocated on the heap. Consider the following case:
int main() {
string someString;
..
}
The local variable is not dynamically allocated; new is not used; however the object still needs to be initialized so the constructor is still called. Note that you did not need to explicitly call the constructor - it is implicit in the language that an appropriate constructor will always be called to initialize an object when it is created.
When you write a 'new expression', the compiler knows to emit instructions to invoke the new operator (to allocate memory as needed) and then to call the constructor (to initialize the object). This happens whether or not you overload the new operator.

Copy constructor understanding

I was going through this to study copy constructor again.
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;
}
OUTPUT:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
I was wondering why it is calling Copy constructor in Line line(10). I think it should call the normal constructor only. I'm not cloning any object here. Please someone explain me this.
The copy constructor is called because the function parameter is passed by value. Here
void display(Line obj)
the function is defined as taking the Line parameter by value. This results in a copy of the argument being made. Had you passed by reference, the copy constructor would not be called
I was wondering why it is calling Copy constructor in Line line(10).
No, it does not.
It just calls the constructor for Line class constructor which takes a int as parameter.
void display(Line obj)
Passes Line object by value and hence copy constructor is called to create the copy being passed to the function.
In C++ function arguments are passsed by value by default. And the copy of these objects is created by calling the copy constructor of that class.

Why destructor is calling after function scope ending when object reference passed as parameter?

Why is the destructor being called after function (pass(sample const &ob1)) scope ends, when object reference is passed as parameter? Why is it creating a new object in function pass(), while we are passing an object reference?
Help me on this, I'm getting memory dump error
#include<iostream>
using namespace std;
class sample
{
public:
int *ptr;
sample()
{
cout<<"this is default constructor & addr "<<this<<endl;
}
sample(int i)
{
cout<<"this is single parameter constructor & addr "<<this<<endl;
ptr=new int[i];
}
void disp()
{
cout<<"hello \n";
}
~sample()
{
cout<<"destructor & addr "<<this;
delete ptr;
}
};
sample pass(sample const& ob1)
{
for(int i=0;i<5;i++)
ob1.ptr[i]=10;
return ob1;
}
int main()
{
sample obj(5);
sample copy;
cout<<"before calling \n";
obj.disp();
pass(obj);
copy.disp();
cout<<"after calling \n";
return 0;
}
That's because you return by value:
sample pass(sample const& ob1)
{
//...
return ob1;
}
And it's not guaranteed that RVO will occur. In this case, I'm not even sure it can occur.
You are returning a sample by value; this involves construction and destruction of a sample (although in certain circumstances it can be optimised away).
Function pass() is creating a new object because the object is being returned by value ,not by reference .
Returning object by value will invoke a copy constructor and a new object will be created (temporary object) which will be destroyed as soon as the function returns.
To avoid creation of a temporary object,try returning object by reference.
Also the default constructor is not initializing the integer pointer causing memory dump error .
sample const& pass(sample const &ob1)
{
for(int i=0;i<5;i++)
ob1.ptr[i]=10;
cout << "pass & addr " << &ob1 << endl ;
return ob1;
}
sample()
{
cout<<"this is default constructor & addr "<<this<<endl;
this->ptr = new (int);
}