Copy Constructor

R

royashish

Hi all ,

A question to the C++ fraternity , Why the Copy constructor ?

Was suggested in Effective C++ , In Case the Object contains a
Char* , a assignment operator = makes the two object point to the
same address . In this case any Of the two Object is destroyed a
memory leak occurs as one of the object stays on the Heap . My
experiments on the same have proved otherwise .

can anyone confirm / add to the need to copy constructors ?

Thanks and regards ,

Ashish
 
S

sam_cit

Hi all ,

A question to the C++ fraternity , Why the Copy constructor ?

Was suggested in Effective C++ , In Case the Object contains a
Char* , a assignment operator = makes the two object point to the
same address . In this case any Of the two Object is destroyed a
memory leak occurs as one of the object stays on the Heap . My
experiments on the same have proved otherwise .

can anyone confirm / add to the need to copy constructors ?

Thanks and regards ,

Ashish

There isn't any memory leak, it would just be a dangling pointer...

You have the answer, the problem is because of a shallow copy and in
order to avoid this problem you need to perform a deep copy in a
function which is invoked by the compiler when objects are assigned or
objects are passed by value or returned by value.

This is not needed for built in types as compiler takes care of it.
It is needed for custom types like Structure, Class etc.
 
J

Juha Nieminen

Was suggested in Effective C++ , In Case the Object contains a
Char* , a assignment operator = makes the two object point to the
same address . In this case any Of the two Object is destroyed a
memory leak occurs as one of the object stays on the Heap . My
experiments on the same have proved otherwise .

Perhaps you didn't understand correctly what Effective C++ was
trying to say.

If a class allocates memory for itself (at the end of a member
pointer) and frees that allocated memory in its destructor, it
requires a copy constructor and assignment operator if instances of
that class need to be copied and assigned. If there's no copy
constructor nor assignment operator and copying/assignment is
performed, it will cause double deletions of the same pointer,
as well as possible accessing of deleted memory.

Of course if the pointer inside the class points to something
not allocated by the class itself, something which the class itself
doesn't need to free but which is deleted somewhere else, then,
naturally, you don't need a copy constructor if it's ok for the
copies to point to the same memory location with that pointer.
 
R

royashish

Perhaps you didn't understand correctly what Effective C++ was
trying to say.

If a class allocates memory for itself (at the end of a member
pointer) and frees that allocated memory in its destructor, it
requires a copy constructor and assignment operator if instances of
that class need to be copied and assigned. If there's no copy
constructor nor assignment operator and copying/assignment is
performed, it will cause double deletions of the same pointer,
as well as possible accessing of deleted memory.

Of course if the pointer inside the class points to something
not allocated by the class itself, something which the class itself
doesn't need to free but which is deleted somewhere else, then,
naturally, you don't need a copy constructor if it's ok for the
copies to point to the same memory location with that pointer.

Hi guys ,

i agree with you that double deletion shall happen as you say .
But when i tried it out , The string elements of the two objects
where pointing to two different memory locations . Thus the very
point of having a copy constructor fails . Even in the case of pass
by value , i found using VC++ , that the temp Objects that come into
exsistence have different addresses . Is this something that has
been corrected in the compiler ?

If you insist i shall again cross check my observations .

Regards ,
Ashish
 
T

terminator

Hi guys ,

i agree with you that double deletion shall happen as you say .
But when i tried it out , The string elements of the two objects
where pointing to two different memory locations . Thus the very
point of having a copy constructor fails . Even in the case of pass
by value , i found using VC++ , that the temp Objects that come into
exsistence have different addresses . Is this something that has
been corrected in the compiler ?

If you insist i shall again cross check my observations .

Regards ,
Ashish- Hide quoted text -

- Show quoted text -

I think you had better post a copy of the class your talking about.

regrads,
FM.
 
R

royashish

I think you had better post a copy of the class your talking about.

regrads,
FM.

#include<iostream>
using namespace std;

class cpchk{
private:
char* name;
int num;
public:
// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;
return name;
}
void setname(const char* acname){
if(name==0)
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
else{
free(name);
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
}
strcpy(name,acname);
}

// Methods for num
int getnum()const{
cout<<"Address:Num>>"<<&num<<endl;
return num;
}
void setnum(const int inum){
num=inum;
}

// Constructors
cpchk(){
cout<<"Constructor called"<<endl;
name=0;
num=0;
}

cpchk(char* acname,int inum){
name=0;
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
strcpy(name,acname);
}

// Destructor
~cpchk(){
cout<<"Destructor called"<<endl;
if(name!=0)
free(name);
}

};

int main(int argc,char** argv){
cpchk a,b;
a.setname("Hitesh");
a.setnum(10);

b.setname("Rajesh");
b.setnum(30);

cout<<endl<<"Before Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

a=b;

cout<<endl<<"After Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

return 0;
}

Heres the code i am talking about , Kindly comment .

Thanks and Regards,

Ashish
 
R

Roy

#include<iostream>
using namespace std;

class cpchk{
private:
char* name;
int num;
public:
// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;
return name;
}
void setname(const char* acname){
if(name==0)
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
else{
free(name);
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
}
strcpy(name,acname);
}

// Methods for num
int getnum()const{
cout<<"Address:Num>>"<<&num<<endl;
return num;
}
void setnum(const int inum){
num=inum;
}

// Constructors
cpchk(){
cout<<"Constructor called"<<endl;
name=0;
num=0;
}

cpchk(char* acname,int inum){
name=0;
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
strcpy(name,acname);
}

// Destructor
~cpchk(){
cout<<"Destructor called"<<endl;
if(name!=0)
free(name);
}

};

int main(int argc,char** argv){
cpchk a,b;
a.setname("Hitesh");
a.setnum(10);

b.setname("Rajesh");
b.setnum(30);

cout<<endl<<"Before Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

a=b;

cout<<endl<<"After Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

return 0;

}

Heres the code i am talking about , Kindly comment .

Thanks and Regards,

Ashish

Constructor called
Constructor called

Before Assignent
Object A
0012FF6C
Address:Name>>0012FF6C
Hitesh
Address:Num>>0012FF70
10
Object B
0012FF64
Address:Name>>0012FF64
Rajesh
Address:Num>>0012FF68
30

After Assignent
Object A
0012FF6C
Address:Name>>0012FF6C
Rajesh
Address:Num>>0012FF70
30
Object B
0012FF64
Address:Name>>0012FF64
Rajesh
Address:Num>>0012FF68
30
Destructor called
Address:Name>>0012FF64
Address:Num>>0012FF68
Address:Object>>0012FF64
Destructor called
Address:Name>>0012FF6C
Address:Num>>0012FF70
Address:Object>>0012FF6C
Press any key to continue

Is what i get along with a Debug assert error .
 
I

Ian Collins

// Destructor
~cpchk(){
cout<<"Destructor called"<<endl;
if(name!=0)
free(name);
}
a=b;

Heres the code i am talking about , Kindly comment .
Two serious errors:

You attempt to free name twice (why the check for 0?), whether or not it
was allocated by malloc.
 
R

Roy

Two serious errors:

You attempt to free name twice (why the check for 0?), whether or not it
was allocated by malloc.

Hi Ian ,

I have checked for 0 , as in the constructor i equate the pointer to
0 , that way my program knows how to check
against freeing a pointer not allocated memory .
I didn't get your point of freeing name twice . There are two
different Objects in the program . Both need to
have their memory freed ?

Kindly clarify ,

Regards,
Ashish
 
I

Ian Collins

Roy said:
Hi Ian ,

I have checked for 0 , as in the constructor i equate the pointer to
0 , that way my program knows how to check
against freeing a pointer not allocated memory .

Freeing NULL is a no-op, so you don't have to check.

In your case, you have no way of telling whether the name points to
dynamic memory.
I didn't get your point of freeing name twice . There are two
different Objects in the program . Both need to
have their memory freed ?
Once you assign one to the other, both have a name pointer pointing to
the same address. Try printing the pointer value in your destructor.
 
R

Roy

Freeing NULL is a no-op, so you don't have to check.

In your case, you have no way of telling whether the name points to
dynamic memory.


Once you assign one to the other, both have a name pointer pointing to
the same address. Try printing the pointer value in your destructor.

Constructor called
Before Assignent
Object A 0012FF6C
Address:Name>>0012FF6C
Address:Num>>0012FF70
Object B 0012FF64
Address:Name>>0012FF64
Address:Num>>0012FF68
After Assignent
Object A 0012FF6C
Address:Name>>0012FF6C
Address:Num>>0012FF70
Object B 0012FF64
Address:Name>>0012FF64
Address:Num>>0012FF68
Address:Object>>0012FF64
Destructor called
Address:Name>>0012FF64
Address:Num>>0012FF68
Address:Object>>0012FF6C
Destructor called
Address:Name>>0012FF6C
Address:Num>>0012FF70

heres what i get :-(

I have understood The NULL thing , i have modified the code to

#include<iostream>
using namespace std;

class cpchk{
private:
char* name;
int num;
public:
// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;
return name;
}
void setname(const char* acname){
if(name==NULL)
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
else{
free(name);
name=NULL;
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
}
strcpy(name,acname);
}

// Methods for num
int getnum()const{
cout<<"Address:Num>>"<<&num<<endl;
return num;
}
void setnum(const int inum){
num=inum;
}

// Constructors
cpchk(){
cout<<"Constructor called"<<endl;
name=NULL;
num=0;
}

cpchk(char* acname,int inum){
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
strcpy(name,acname);
}

// Destructor
~cpchk(){
cout<<"Address:Object>>"<<this<<endl;
cout<<"Destructor called"<<endl;
cout<<"Address:Name>>"<<&name<<endl;
cout<<"Address:Num>>"<<&num<<endl;

if(name!=NULL)
free(name);
name=NULL;
}


};

int main(int argc,char** argv){
cpchk a,b;
a.setname("Hitesh");
a.setnum(10);

b.setname("Rajesh");
b.setnum(30);

cout<<endl<<"Before Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

a=b;

cout<<endl<<"After Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

return 0;
}
 
I

int2str

On Jul 30, 9:24 am, Ian Collins <[email protected]> wrote:

Snipped previous iterations.
heres what i get :-(

I have understood The NULL thing , i have modified the code to

#include<iostream>
using namespace std;

class cpchk{
private:
char* name;
int num;
public:
// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;

Here you are not printing the content of the pointer, but the address
of the pointer. This will not change during the live of the project.
Change this too (for example):

cout<<"Address:Name>>"<< hex << (long)name<<endl;

Don't forget to include said:
return name;
}
void setname(const char* acname){
if(name==NULL)
name=(char*)malloc((strlen(acname)+1)*sizeof(char));

In C++, you'd generally use "new" here, not "malloc".
else{
free(name);
name=NULL;
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
}

The if/else logic here can be simplified and redundant code can be
removed.
You think about how - ask if you need to.
strcpy(name,acname);
}

// Methods for num
int getnum()const{
cout<<"Address:Num>>"<<&num<<endl;
return num;
}
void setnum(const int inum){
num=inum;
}

// Constructors
cpchk(){
cout<<"Constructor called"<<endl;
name=NULL;
num=0;

Lookup "initialization lists" in this newsgroup.
}

cpchk(char* acname,int inum){
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
strcpy(name,acname);
}

inum is not used in this function.
// Destructor
~cpchk(){
cout<<"Address:Object>>"<<this<<endl;
cout<<"Destructor called"<<endl;
cout<<"Address:Name>>"<<&name<<endl;

Same problem here. You're displaying the address of the pointer, not
it's contents (what it is pointing too).
cout<<"Address:Num>>"<<&num<<endl;

if(name!=NULL)
free(name);

You can use "delete []" here if you use "new" to allocate the string.
name=NULL;
}

};

int main(int argc,char** argv){
cpchk a,b;
a.setname("Hitesh");
a.setnum(10);

b.setname("Rajesh");
b.setnum(30);

cout<<endl<<"Before Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

a=b;

This doesn't call the copy constructor (the title of your thread), but
instead invokes the assignment operator.
cout<<endl<<"After Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;

cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

return 0;

}

Hope this helps.

Cheers,
Andre
 
R

Roy

On Jul 30, 9:24 am, Ian Collins <[email protected]> wrote:

Snipped previous iterations.




heres what i get :-(
I have understood The NULL thing , i have modified the code to
#include<iostream>
using namespace std;
class cpchk{
private:
char* name;
int num;
public:
// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;

Here you are not printing the content of the pointer, but the address
of the pointer. This will not change during the live of the project.
Change this too (for example):

cout<<"Address:Name>>"<< hex << (long)name<<endl;

Don't forget to include said:
return name;
}
void setname(const char* acname){
if(name==NULL)
name=(char*)malloc((strlen(acname)+1)*sizeof(char));

In C++, you'd generally use "new" here, not "malloc".
else{
free(name);
name=NULL;
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
}

The if/else logic here can be simplified and redundant code can be
removed.
You think about how - ask if you need to.


strcpy(name,acname);
}
// Methods for num
int getnum()const{
cout<<"Address:Num>>"<<&num<<endl;
return num;
}
void setnum(const int inum){
num=inum;
}
// Constructors
cpchk(){
cout<<"Constructor called"<<endl;
name=NULL;
num=0;

Lookup "initialization lists" in this newsgroup.
cpchk(char* acname,int inum){
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
strcpy(name,acname);
}

inum is not used in this function.


// Destructor
~cpchk(){
cout<<"Address:Object>>"<<this<<endl;
cout<<"Destructor called"<<endl;
cout<<"Address:Name>>"<<&name<<endl;

Same problem here. You're displaying the address of the pointer, not
it's contents (what it is pointing too).
cout<<"Address:Num>>"<<&num<<endl;
if(name!=NULL)
free(name);

You can use "delete []" here if you use "new" to allocate the string.


name=NULL;
}

int main(int argc,char** argv){
cpchk a,b;
a.setname("Hitesh");
a.setnum(10);

cout<<endl<<"Before Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;
cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;

This doesn't call the copy constructor (the title of your thread), but
instead invokes the assignment operator.


cout<<endl<<"After Assignent"<<endl;
cout<<"Object A"<<endl;
cout<<&a<<endl;
cout<<a.getname()<<endl;
cout<<a.getnum()<<endl;
cout<<"Object B"<<endl;
cout<<&b<<endl;
cout<<b.getname()<<endl;
cout<<b.getnum()<<endl;
return 0;

Hope this helps.

Cheers,
Andre

1.
This is what i have been missing :-(

cout<<"Address:Name>>"<< hex << (long)name<<endl;
Don't forget to include <iomanip> for "hex".

2.
I have read that even in C++ we use malloc and free for primitive data
types . Is it wrong ?I guess i should search ?

3.
Yes i know about the Initialization lists , but am unsure if i can
use them to bypass new/malloc ?


4. Finally i have proff that why copy constructor is vital !

0012FF64
Address:Name>>4819f0
Rajesh
Address:Num>>1e
1e

After Assignent
Object A 0012FF6C
Address:Name>>4819f0 Rajesh
Address:Num>>1e
Object B 0012FF64
Address:Name>>4819f0 Rajesh
Address:Num>>1e <---- ??
1e <------??
Address:Object>>12ff64
Address:Num>>1e
Address:Name>>4819f0 <--------- Same
Address:Num>>1e <--------- ??
Address:Object>>12ff6c
Address:Num>>1e
Address:Name>>4819f0 <--------- Same
Address:Num>>1e <-------??

Thanks a ton Andre .
 
J

James Kanze

Better:
std::cout << "Address::Name>> :"

In C++, you'd generally use std::string, and be done with it:).
But yes, the new operator should definitly be preferred to
malloc. (One might also add that sizeof(char) is guaranteed to
be one.)

The if/else logic can be completely removed. There's no need
for the if, nor setting name to NULL:

delete [] name ;
name = new char[ strlen( acname ) + 1 ] ;

(With std::string, of course, the entire function becomes
simply:
name = acname ;
..)

Or any good C++ book.
}
cpchk(char* acname,int inum){
name=(char*)malloc((strlen(acname)+1)*sizeof(char));
strcpy(name,acname);
}
inum is not used in this function.
// Destructor
~cpchk(){
cout<<"Address:Object>>"<<this<<endl;
cout<<"Destructor called"<<endl;
cout<<"Address:Name>>"<<&name<<endl;
Same problem here. You're displaying the address of the pointer, not
it's contents (what it is pointing too).
cout<<"Address:Num>>"<<&num<<endl;
if(name!=NULL)
free(name);
You can use "delete []" here if you use "new" to allocate the string.
name=NULL;
}
};

Most obviously, there's no assignment operator.

I would strongly recommend that the poster acquire a copy of
Scott Meyer's "Effective C++", and read it carefully.
2.
I have read that even in C++ we use malloc and free for primitive data
types . Is it wrong ?I guess i should search ?

I never use malloc and free in C++, except when implementing a
global operator new and operator delete replacement. Malloc and
free allocate raw memory, and are not type safe.
3.
Yes i know about the Initialization lists , but am unsure if i can
use them to bypass new/malloc ?

They don't bypass anything. For pointers, there's absolutely no
difference between:

MyClass::MyClass()
: somePointer( new Whatever[ howmany ] )
{
}

and:

MyClass::MyClass()
{
somePointer = new Whatever[ howmany ] ;
}

Except that in the first case, there is no way that later
modification can accidentally access an uninitialized pointer.
 
D

Dima Stopel

Freeing NULL is a no-op, so you don't have to check.

In your case, you have no way of telling whether the name points to
dynamic memory.


Once you assign one to the other, both have a name pointer pointing to
the same address. Try printing the pointer value in your destructor.

I that one of the problems is in the following function:

// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;
return name;
}

You print the pointer to pointer to name and not the actual value of
the pointer.
If you change this line: cout<<"Address:Name>>"<<&name<<endl;
to this line: cout<<"Address:Name>>"<<(void*)name<<endl;
you will get the following output:

Constructor called
Constructor called

Before Assignent
Object A
0012FF50
Address:Name>>00356328
Hitesh
Address:Num>>0012FF54
10
Object B
0012FF40
Address:Name>>00356370
Rajesh
Address:Num>>0012FF44
30

After Assignent
Object A
0012FF50
Address:Name>>00356370
Rajesh
Address:Num>>0012FF54
30
Object B
0012FF40
Address:Name>>00356370
Rajesh
Address:Num>>0012FF44
30
Press any key to continue . . .
Destructor called
Destructor called

After the copy operation the name addresses are the same. This is what
you have expected, not ?
 
R

Roy

I that one of the problems is in the following function:

// Methods for name
char* getname()const{
cout<<"Address:Name>>"<<&name<<endl;
return name;
}

You print the pointer to pointer to name and not the actual value of
the pointer.
If you change this line: cout<<"Address:Name>>"<<&name<<endl;
to this line: cout<<"Address:Name>>"<<(void*)name<<endl;
you will get the following output:

Constructor called
Constructor called

Before Assignent
Object A
0012FF50
Address:Name>>00356328
Hitesh
Address:Num>>0012FF54
10
Object B
0012FF40
Address:Name>>00356370
Rajesh
Address:Num>>0012FF44
30

After Assignent
Object A
0012FF50
Address:Name>>00356370
Rajesh
Address:Num>>0012FF54
30
Object B
0012FF40
Address:Name>>00356370
Rajesh
Address:Num>>0012FF44
30
Press any key to continue . . .
Destructor called
Destructor called

After the copy operation the name addresses are the same. This is what
you have expected, not ?

Yes , your observation with the code is correct , Its a fault and
actually printing the pointer to a pointer .
and yes after the copy operation the name addresses are the
same :) .

Thanks
Dima
 
R

Roy

Yes , your observation with the code is correct , Its a fault and
actually printing the pointer to a pointer .
and yes after the copy operation the name addresses are the
same :) .

Thanks
Dima
class x{
public:
char* getname(){return b}
x():b(NULL){}
x(acName):b(acName){}
~x(){}
private:
char* b;
};
main(){
x *a;
a=new x("ashish");
cout<<a->getname()<<endl;
delete a;
}

Kindly point out the errors in this code ?
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

class x{
public:
char* getname(){return b}
x():b(NULL){}
x(acName):b(acName){}
~x(){}
private:
char* b;
};
main(){
x *a;
a=new x("ashish");
cout<<a->getname()<<endl;
delete a;
}

Kindly point out the errors in this code ?

You probably want to store a copy of the name, not just a pointer to it.
Consider what would happen if someone changed the text pointed to by b.
 
R

Roy

You probably want to store a copy of the name, not just a pointer to it.
Consider what would happen if someone changed the text pointed to by b.

Hmmm , Ok , so what should be the right way of doing it through an
initialization list ? should i use the String type instead of a
char* ?

Regards ,
Ashish
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

On 2007-07-30 12:21, Roy wrote:
[snip]
You probably want to store a copy of the name, not just a pointer to it.
Consider what would happen if someone changed the text pointed to by b.

Hmmm , Ok , so what should be the right way of doing it through an
initialization list ? should i use the String type instead of a
char* ?

The general advice is to always use string instead of char* so that's
probably a good solution. If for some reason you can't use string, you
can allocate the space in the initialisation list and copy the string in
the constructor body (or do both in the body).

You can't do everything in the initialisation list, it's only an
optimisation to prevent calling the default constructor on all members
before assigning them (and for some classes where default constructors
are not available they are necessary). Consider the following code:

#include <string>

class Foo {
std::string str;
public:
Foo(std::string& s) {
str = s;
}
};

int main() {
std::string text("Hello World");
Foo f(text);
}

What happens when f is created is that first f.str is constructed using
the default constructor, then the text "Hello World" is assigned to it.
If we use an initialisation list instead:

Foo(std::string& s) : str(s) {}

what happens is that f.str will be constructed with the text "Hello
World" directly and no assignment is needed.

In this example there's probably not much difference in execution speed
but if you run the code many many times, or if you have some other kind
of object, it can have quite a big impact.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,128
Latest member
ElwoodPhil
Top