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.
Related
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.
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.
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.
When i run the following program in XCode Version 5.1.1,
#include <iostream>
class MyClass
{
public:
MyClass() { std::cout << "MyClass Cons " << this << std::endl;}
~MyClass() { std::cout << "MyClass Dest " << this << std::endl;}
};
void Func(MyClass myClass)
{
}
int main(int argc, const char * argv[])
{
MyClass myClass1;
Func(myClass1);
return 0;
}
The output i get is
MyClass Cons 0x7fff5fbff918
MyClass Dest 0x7fff5fbff910
MyClass Dest 0x7fff5fbff918
Why is the destructor triggering twice and constructor only once?
The object is destroyed once, as you can see from the pointer values. You also see the destruction of another object. This object is a copy of the original.
By passing the object by value, the copy-constructor is invoked. Since this constructor does not print something, you do not see it in your output.
Add it to the class definition:
MyClass(const MyClass & other) { std::cout << "MyClass Copy-Cons " << this << " from " << &other << std::endl;}
And it should appear:
MyClass Cons 0x7fff1beee7ee
MyClass Copy-Cons 0x7fff1beee7ef from 0x7fff1beee7ee
MyClass Dest 0x7fff1beee7ef
MyClass Dest 0x7fff1beee7ee
The copy is created when you enter Func(). The copy is destroyed when it goes out of scope. This happens when you exit Func(). Finally, the original is destroyed when you exit the main() function.
The reason that you are seeing two destructor is because you are pass the arguments by value. Passing by value calls the copy constructor..
First Destructor:
At the end of the func function, the object goes out of scope, hence, it is destructed.
Second Destructor:
When the program end, the object is destructed.
My suggestion to remove the first destructor is to pass the object by reference rather than by value.
For example,
void Func(MyClass &myClass)
{
}
So now the output will have only:
MyClass Cons 0x7fff5fbff918
MyClass Dest 0x7fff5fbff918
Here the object is constructed twice(as everyone mentioned above). Hence 2 constructor + 2 destructor are called. The reason you are seeing 1 constructor is because you have NOT defined the Copy Constructor. CC is called when a copy is made for the pass-by-value operation.
add the copy constructor and then you can see both the constructor called.
Add Copy constructor - MyClass(const MyClass& obj) { std::cout << "MyClass Copy Cons " << this << std::endl;}
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.