When copy constructors become handy?

U

utab

Dear all,

So passing and returning a class object is the time when to include the
definition of the copy constructor into the class definition. But if we
don't call by value or return by value, we do not need to use the
copy-constructor. So depending on the above reasoning I can avoid call
by value and return by value for class objects, this bypasses the
problem or it seems to me like that.

Could any one give me some simple examples when copy constructors are
indispensible tools in C++ class implementations?

Thx
 
M

Mark P

utab said:
Dear all,

So passing and returning a class object is the time when to include the
definition of the copy constructor into the class definition.

Not necessarily. There is a default copy ctor provided automatically.
You only need to write your own if the default is not satisfactory.
But if we
don't call by value or return by value, we do not need to use the
copy-constructor. So depending on the above reasoning I can avoid call
by value and return by value for class objects, this bypasses the
problem or it seems to me like that.

Function arguments and return values aren't the only situations where
objects are copied. Sometimes you just need to make a copy:

A a1;
A a2 = a1; // copy ctor called

Besides, you may find that never calling or returning by value is
incredibly onerous. What do you have against copy ctors?
 
G

Gavin Deane

utab said:
Dear all,

So passing and returning a class object is the time when to include the
definition of the copy constructor into the class definition.

Passing by value and returning by value are two ways of invoking copy
construction for objects of class type. But just because the copy
constructor is used doesn't mean you need to define it yourself. If you
don't define it, the compiler will do it for you. The compiler
generated copy constructor will perform a memberwise copy of all data
members and will copy base class objects using their copy constructors.
Unless that is not sufficient for your needs, you do not need to define
the copy constructor, even if you do copy objects.
But if we
don't call by value or return by value, we do not need to use the
copy-constructor.

Not true.

std::string s1("text");
std::string s2(s1);

s2 is constructed using the copy constructor of the std::string class,
but nothing is passed or returned by value.
So depending on the above reasoning I can avoid call
by value and return by value for class objects, this bypasses the
problem or it seems to me like that.

What problem?
Could any one give me some simple examples when copy constructors are
indispensible tools in C++ class implementations?

You should write a copy constructor for any class where the compiler
generated copy constructor is not sufficient. Generally this means
classes that own resources, e.g. memory referred to by a bald pointer.
Google for the "rule of three" too. If you need to write your own copy
constructor, you probably need to write your own assignment operator
and destructor as well.

Notice that the decision whether to write your own copy constructor or
rely on the compiler generated one has *nothing* to do with whether you
think the code you're about to write will copy objects. Even if you
don't plan to copy any objects immediately, you should still write the
copy constructor (or disable copying - see below) if the compiler
generated copy constructor is not sufficient. Otherwise, one day you or
someone else will come along, write some new code that does copying and
unwittingly introduce bugs because the wrong copy constructor is used.

You have another option too. If you want to disable copying for your
class, declare the copy constructor private. Declare the assignment
operator private too because it certainly makes no sense to disable
copying but allow assignment.

class foo
{
private:
foo(const foo&);
foo& operator=(const foo&);
};

An attempt to copy or assign foo objects will result in a compile
error. Declaring your own copy constructor (even though it is private
and you have not provided a definition) suppresses the compiler
generated one.

Gavin Deane
 
G

Gavin Deane

utab said:
for this the default copy constructor does the trick or ??

What do you mean by "default copy constructor"? There are default
constructors and there are copy constructors. They are two different
things.

As I said in my other post in this thread (I appreciate you may not
have seen that yet), *if* you do not declare a copy constructor, the
compiler *will* generate one for you. A class can either have the
compiler generated copy constructor or a copy constructor you write. It
cannot have both.

Whether it is appropriate to rely on the compiler generated copy
constructor has *nothing* to do with the way in which copying is
invoked (e.g. creating a variable like the code above vs. passing an
object to a function by value), but has everything to do with the
internal nature of the object.

Gavin Deane
 
U

utab

if I do not supply mine for the class, for simple copy operations is
this enough(I think not because the calling and destruction of the
objects do not match then but I am nor sure s I will check that...)

Thx.
 
M

Michiel.Salters

utab said:
if I do not supply mine for the class, for simple copy operations is
this enough(I think not because the calling and destruction of the
objects do not match then but I am nor sure s I will check that...)

They will match - one constructor will be called for every destructor
called.
Of course, there can be different constructors (default/copy/...) so if
you want
to count the number of objects constructed you'll have to count every
constructor call (including the compiler-generated!)

In general, the rule-of-three applies: you need to write a copy
constructor,
assignment, and a destructor if you need any of those.

HTH,
Michiel Salters
 
U

utab

I tried something simple to better understand the construction
involving copy constructors and the rule of three, but I have several
questions;

#include <iostream>

using std::cout;
using std::endl;

class X{
public:
X(int a){x=a;++count;cout<< "ctor" << std::endl;cout<< count <<
std::endl;}
X(const X&){++count;cout<< "cctor" << std::endl;cout<< count <<
std::endl;}
// X& operator=(X& rhs){x=rhs.x;return *this;}
int getx(){return x;}
~X(){--count;cout<< "dtor" << std::endl; cout<< count <<
std::endl;}
private:
int x;
static int count;

};
int X::count = 0;
int main(){
X a(5),b(10);
//X c(a);
b=a;
cout << b.getx() << std::endl;
return 0;
}

If I comment the overloaded = operator, I can not see the output for my
copy constructor. I get

ctor
1
ctor
2
5
dtor
1
dtor
0

When I initialize an object with another one cctor works and
ctor
1
ctor
2
cctor
3
5
dtor
2
dtor
1
dtor
0

When the object with object initialization is commented and = operator
is used but the copy constructor is not used so , while using the rule
of three, whichever is appropriate will be used is that true. Since I
am using =, this one is used. I am a bit confused.. :-((
 
G

Gavin Deane

utab said:
I tried something simple to better understand the construction
involving copy constructors and the rule of three, but I have several
questions;

#include <iostream>

using std::cout;
using std::endl;

class X{
public:
X(int a){x=a;++count;cout<< "ctor" << std::endl;cout<< count <<
std::endl;}
X(const X&){++count;cout<< "cctor" << std::endl;cout<< count <<
std::endl;}
// X& operator=(X& rhs){x=rhs.x;return *this;}
int getx(){return x;}
~X(){--count;cout<< "dtor" << std::endl; cout<< count <<
std::endl;}
private:
int x;
static int count;

};
int X::count = 0;
int main(){
X a(5),b(10);
//X c(a);
b=a;
cout << b.getx() << std::endl;
return 0;
}

If I comment the overloaded = operator, I can not see the output for my
copy constructor.

I don't know what you mean. There are two lines commented out in your
code above. One is the definition of the assignment operator in the
class. The other is X c(a); which copy constructs a new object c from
the object a. Copy construction is a completely different thing from
assignment so commenting out the assignment operator is irrelevant to
what happens when you try and copy construct an object. The line X
c(a); is the only occurrance of copy construction in your code so if
you comment out that line it is not surprising that you don't see your
copy constructor called. b=a; is assignment - it has nothing to do with
copy construction.

Your assignment operator is identical in effect to the one the compiler
would have generated if you hadn't done it yourself, so whether yours
is commented out or not has no effect on the behaviour of your code.
I get

ctor
1
This is the construction of object a using the value 5
This is the construction of object b using the value 10
This is the result of b.getx() after the assignment b=a; changes the
value of x within b to 5.
This is the destruction of object b
This is the destruction of object a

When I initialize an object with another one cctor works and

I assume what you mean here is that you've uncommented the line X c(a);
to see what difference it makes.
This is the construction of object a using the value 5
This is the construction of object b using the value 10
This is the copy construction of object c from object a
This is the result of b.getx() after the assignment b=a; changes the
value of x within b to 5.
This is the destruction of object c
This is the destruction of object b
This is the destruction of object a
When the object with object initialization is commented and = operator
is used but the copy constructor is not used so , while using the rule
of three, whichever is appropriate will be used is that true. Since I
am using =, this one is used. I am a bit confused.. :-((

Construction (whether it be copy construction or any other form of
construction) is a completely different thing from assignment. The copy
constructor is used when *a new object* is being constructed as a copy
of an existing object. The assignment operator is used when *an object
that already exists* has a new value assigned to it.

Gavin Deane
 
B

benben

utab said:
Dear all,

So passing and returning a class object is the time when to include the
definition of the copy constructor into the class definition. But if we
don't call by value or return by value, we do not need to use the
copy-constructor. So depending on the above reasoning I can avoid call
by value and return by value for class objects, this bypasses the
problem or it seems to me like that.

Could any one give me some simple examples when copy constructors are
indispensible tools in C++ class implementations?

Thx

In addition to all other posts, may I remind you without a copy
constructor the standard containers can be quite embarrassing to use:

#include <vector>
#include <list>

class C
{
private:
C(const C&);
public:
C(){}
~C(){}
};

int main()
{
std::vector<C> v; // ERROR
std::list<C> l; // ERROR
std::deque<C> d; // ERROR
}

Regards,
Ben
 

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,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top