By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,962 Members | 1,767 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,962 IT Pros & Developers. It's quick & easy.

Copy constructor question

P: n/a
Hi guys,

I have a simple question. If I have a class like:

class A {
A();
~A();
A(A& a);
A(int i);

int myvalue;
};

So there's a copy constructor for integers:

A::A(int i) { myvalue = i;}

But if I also want copy constructors for unsigned int, long, float,
double, long double etc, do I have to write them all out? All bodies of
these copy constructors are exactly the same:

A::A(T& t) { myvalue = t;}

Or can templates help me without having to write out all variants?

And what if I have to deal with other classes/types which are not
clearly a 'simple scalar'? For example 'complex'? This needs another
code body because then I need to get the real value (for example):

A::A(complex<double>& c) { myvalue = c.real();}

And of course the complex variable comes in various variants like
double, float, etc...

Thanks for any hints,

Jeroen
Apr 18 '07 #1
Share this Question
Share on Google+
19 Replies


P: n/a
Jeroen wrote:
Hi guys,

I have a simple question. If I have a class like:

class A {
A();
~A();
A(A& a);
A(int i);

int myvalue;
};

So there's a copy constructor for integers:

A::A(int i) { myvalue = i;}
No, this isn't a copy constructor, there is only one of those (A(A& a),
which should real be A(cont A& a)). It s a constructor.
But if I also want copy constructors for unsigned int, long, float,
double, long double etc, do I have to write them all out?
No, not if there is an automatic conversion from the type to int. If
there is, the int constructor will be used.

--
Ian Collins.
Apr 18 '07 #2

P: n/a
Jeroen wrote:
Hi guys,

I have a simple question. If I have a class like:

class A {
A();
~A();
A(A& a);
A(int i);

int myvalue;
};
The above class is probably defective in that it has a explicit
copy constructor but no copy-assignment operator. If you have
non-standard copy semantics it needs to be done in both places.
>
So there's a copy constructor for integers:

A::A(int i) { myvalue = i;}
The term here is NOT copy-constructor. A copy constructor is
called with a cv-qualified type of the same class. What you
have here is a "coverting constructor" that is a constructor
that can be called with one argument (other than the same class)
and is NOT declared explicit.
>
But if I also want copy constructors for unsigned int, long, float,
double, long double etc, do I have to write them all out?
If all you are going to do is assign to i, why do you think you
need all of these. The single converting constructor from int
would work fine.
A::A(complex<double>& c) { myvalue = c.real();}
Can you say specialization? I knew you could.

typedef <class TA(const complex<T>& c) { myvalue = c.real(); }

You should really make your stuff const correct.
Apr 18 '07 #3

P: n/a
Ian Collins schreef:
Jeroen wrote:
>Hi guys,

I have a simple question. If I have a class like:

class A {
A();
~A();
A(A& a);
A(int i);

int myvalue;
};

So there's a copy constructor for integers:

A::A(int i) { myvalue = i;}
No, this isn't a copy constructor, there is only one of those (A(A& a),
which should real be A(cont A& a)). It s a constructor.
>But if I also want copy constructors for unsigned int, long, float,
double, long double etc, do I have to write them all out?

No, not if there is an automatic conversion from the type to int. If
there is, the int constructor will be used.
OK, thanks for the answer. And you're right (of course), there's only
one copy constructor. Very sloppy of me :-)
Apr 19 '07 #4

P: n/a
Ron Natalie schreef:
Jeroen wrote:
>Hi guys,

I have a simple question. If I have a class like:

class A {
A();
~A();
A(A& a);
A(int i);

int myvalue;
};
The above class is probably defective in that it has a explicit
copy constructor but no copy-assignment operator. If you have
non-standard copy semantics it needs to be done in both places.
Yes, I know. But I tried to leave as much as 'overhead' out (at least
those things that seem not te be important for the question) from the
example.
>>
So there's a copy constructor for integers:

A::A(int i) { myvalue = i;}

The term here is NOT copy-constructor. A copy constructor is
called with a cv-qualified type of the same class. What you
have here is a "coverting constructor" that is a constructor
that can be called with one argument (other than the same class)
and is NOT declared explicit.
Right, very sloppy of me. I knew that...
>
>>
But if I also want copy constructors for unsigned int, long, float,
double, long double etc, do I have to write them all out?

If all you are going to do is assign to i, why do you think you
need all of these. The single converting constructor from int
would work fine.
> A::A(complex<double>& c) { myvalue = c.real();}

Can you say specialization? I knew you could.

typedef <class TA(const complex<T>& c) { myvalue = c.real(); }

You should really make your stuff const correct.
OK, I'll look the 'template specialization' up on the Internet. Thanks
for the example and reply Ron!
Apr 19 '07 #5

P: n/a
Jeroen wrote:
I have a simple question. If I have a class like:

class A {
A();
~A();
A(A& a);
A(int i);

int myvalue;
};
You made several mistakes.
cat A.h
#ifndef A_H
#define A_H
#include <iostream>

class A {
private:
int myvalue;
public:
A(void): myvalue(0) { } // default
A(int i): myvalue(i) { } // explicit
A(A& a): myvalue(a.myvalue) { }// copy
~A(void) { myvalue = 0; } // destructor

friend
std::ostream& operator <<(std::ostream& os, const A& a) {
return os << a.myvalue;
}
};

#endif//A_H
cat main.cc
#include "A.h"

int main (int argc, char* argv[]) {
A a(13);
std::cout << "a = " << a << std::endl;
return 0;
}
g++ -Wall -ansi -O2 -o main main.cc
./main
a = 13

You should test your code before posting it to this newsgroup.
Your constructors and destructor should be public
so that you can use them.
Data should be private.
You need some sort of access function (operator << in this case)
so that you can use the object.

There are implicit conversions to int
so the compiler will use them if you don't provide
explicit constructors for unsigned int etc.

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Apr 19 '07 #6

P: n/a
E. Robert Tisdale wrote:
>
You made several mistakes.
cat A.h
#ifndef A_H
#define A_H
#include <iostream>

class A {
private:
int myvalue;
public:
A(void): myvalue(0) { } // default
This is a C style of declaring/defining functions. C++ does not use void
for empty parameter list.
A(int i): myvalue(i) { } // explicit
A(A& a): myvalue(a.myvalue) { }// copy
Copy constructor is missing const. It should be:
A( const A &a): myvalue( a.myvalue){}
~A(void) { myvalue = 0; } // destructor
Same comment as for the constructor.
BTW why assign 0 to myvalue?
Apr 20 '07 #7

P: n/a
anon wrote:
E. Robert Tisdale wrote:
>>
You made several mistakes.
> cat A.h
#ifndef A_H
#define A_H
#include <iostream>

class A {
private:
int myvalue;
public:
A(void): myvalue(0) { } // default

This is a C style of declaring/defining functions. C++ does not use
void for empty parameter list.
> A(int i): myvalue(i) { } // explicit
A(A& a): myvalue(a.myvalue) { }// copy

Copy constructor is missing const. It should be:
A( const A &a): myvalue( a.myvalue){}
> ~A(void) { myvalue = 0; } // destructor

Same comment as for the constructor.
BTW why assign 0 to myvalue?
In addition to those comments, the two c-tors (the default and the
parameterized on 'int') should be made into one (the new default):

A(int i = 0) : myvalue(i) {}

And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient. The
same for the destructor -- there is no need in it, apparently.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 20 '07 #8

P: n/a
On Apr 20, 3:09 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:

[...]
In addition to those comments, the two c-tors (the default and the
parameterized on 'int') should be made into one (the new default):
A(int i = 0) : myvalue(i) {}
Both solutions are possible. Which one you prefer is a question
of style and taste; there's certainly no "should" about it.
And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.
Still, most coding guidelines would require an explicit one, to
avoid making it inline.
The
same for the destructor -- there is no need in it, apparently.
Ditto.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 20 '07 #9

P: n/a
James Kanze wrote:
On Apr 20, 3:09 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:

[...]
>In addition to those comments, the two c-tors (the default and the
parameterized on 'int') should be made into one (the new default):
> A(int i = 0) : myvalue(i) {}

Both solutions are possible. Which one you prefer is a question
of style and taste; there's certainly no "should" about it.
Why 'no "should"'? "Should" does not exclude "possible". And I
do not agree that minimizing the number of functions is arbitrary.
It's definitely _better_.
>And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.

Still, most coding guidelines would require an explicit one, to
avoid making it inline.
How would you "avoid maing it inline" by keeping it in the class
definition?
>The
same for the destructor -- there is no need in it, apparently.

Ditto.
<shrug>

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 20 '07 #10

P: n/a
James Kanze wrote:
Victor Bazarov wrote:
>And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.

Still, most coding guidelines would require an explicit one, to
avoid making it inline.
Victor is correct of course.
Actually, I would write

//A(const A& a): myvalue(a.myvalue) { }// copy

just to document the fact that I didn't forget the copy constructor.

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Apr 21 '07 #11

P: n/a
E. Robert Tisdale wrote:
James Kanze wrote:
>Victor Bazarov wrote:
>>And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.


Still, most coding guidelines would require an explicit one, to
avoid making it inline.


Victor is correct of course.
Actually, I would write

//A(const A& a): myvalue(a.myvalue) { }// copy

just to document the fact that I didn't forget the copy constructor.
That's silly, what happens when the class innards change? You have to
maintain the unused constructor.

If anything, write

//A(const A&);// copy

--
Ian Collins.
Apr 21 '07 #12

P: n/a
On Apr 20, 11:36 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
James Kanze wrote:
On Apr 20, 3:09 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
[...]
In addition to those comments, the two c-tors (the default and the
parameterized on 'int') should be made into one (the new default):
A(int i = 0) : myvalue(i) {}
Both solutions are possible. Which one you prefer is a question
of style and taste; there's certainly no "should" about it.
Why 'no "should"'? "Should" does not exclude "possible".
At least in the English I'm most familiar with (that of the
midwest USA), should is a polite form of the imperative. You
*should* adopt the style required by the coding guidelines where
you work. You *can* omit defining the copy constructor in such
cases if the coding guidelines (or other considerations) don't
require it.

As a general rule, in the absense of some specific guideline
otherwise, I will omit it in local classes used only within my
implementation, but provide it explicitly in "published"
classes; those on whose interface other classes, written by
other people, depend. But there are exceptions. In both
directions.
And I do not agree that minimizing the number of functions is
arbitrary. It's definitely _better_.
Except that you don't minimize the number of functions. There
are exactly the same number of functions in both cases.
And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.
Still, most coding guidelines would require an explicit one, to
avoid making it inline.
How would you "avoid maing it inline" by keeping it in the class
definition?
Every coding guideline I've seen forbids defining functions in
the class definition.

We are talking about professional programming, aren't we?
Obviously, if it's just for your own personal satisfaction, you
do whatever gives you the most satisfaction.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 21 '07 #13

P: n/a
On Apr 21, 3:10 am, Ian Collins <ian-n...@hotmail.comwrote:
E. Robert Tisdale wrote:
James Kanze wrote:
Victor Bazarov wrote:
>And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.
Still, most coding guidelines would require an explicit one, to
avoid making it inline.
Victor is correct of course.
Actually, I would write
//A(const A& a): myvalue(a.myvalue) { }// copy
just to document the fact that I didn't forget the copy constructor.
That's silly, what happens when the class innards change? You have to
maintain the unused constructor.
If anything, write
//A(const A&);// copy
More usually, I will have a documentation section encompassing
all of the constructors (plus assignment, destruction and swap);
in the rare cases where I use the compiler generated version, I
will mention this there; as a general rule, it's probably worth
mentionning whether copy and assignment are supported as part of
the class documentation, rather than at the individual function
level.

And of course, even if you count on the compiler generated
forms, you still have to document them. So letting the compiler
do the generation doesn't really save much work. (And if your
shop uses Doxygen, or something along those lines, how do you
make the compiler generated defaults show up in the generated
documentation?)

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 21 '07 #14

P: n/a
Ian Collins wrote:
E. Robert Tisdale wrote:
>James Kanze wrote:
>>Victor Bazarov wrote:

And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient.

Still, most coding guidelines would require an explicit one, to
avoid making it inline.

Victor is correct of course.
Actually, I would write

//A(const A& a): myvalue(a.myvalue) { }// copy

just to document the fact that I didn't forget the copy constructor.
That's silly. What happens when the class innards change?
You have to maintain the unused constructor.
Well, the problem with any documentation is that
you must maintain it just like it was code.
If anything, write

//A(const A&);// copy
Which means that you declared but forgot to define the copy constructor?

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Apr 21 '07 #15

P: n/a
In message <11**********************@e65g2000hsc.googlegroups .com>,
James Kanze <ja*********@gmail.comwrites
>On Apr 20, 11:36 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
[... on explicitly writing what the compiler would do anyway]
>
>And I do not agree that minimizing the number of functions is
arbitrary. It's definitely _better_.

Except that you don't minimize the number of functions. There
are exactly the same number of functions in both cases.
But there are more *user-written* functions which have to be maintained
when you add more data members. And the compiler is better at keeping
track of those members - in three different functions - than I am.

--
Richard Herring
Apr 25 '07 #16

P: n/a
In message <f0**********@news.datemas.de>, Victor Bazarov
<v.********@comAcast.netwrites
>anon wrote:
>E. Robert Tisdale wrote:
>>>
You made several mistakes.

cat A.h
#ifndef A_H
#define A_H
#include <iostream>

class A {
private:
int myvalue;
public:
A(void): myvalue(0) { } // default

This is a C style of declaring/defining functions. C++ does not use
void for empty parameter list.
>> A(int i): myvalue(i) { } // explicit
Not explicit without the "explicit" keyword.
>> A(A& a): myvalue(a.myvalue) { }// copy

Copy constructor is missing const. It should be:
A( const A &a): myvalue( a.myvalue){}
>> ~A(void) { myvalue = 0; } // destructor

Same comment as for the constructor.
BTW why assign 0 to myvalue?

In addition to those comments, the two c-tors (the default and the
parameterized on 'int') should be made into one (the new default):

A(int i = 0) : myvalue(i) {}

And there is probably no need for the copy c-tor as it's implemented.
The one the compiler will generate is absolutely sufficient. The
same for the destructor -- there is no need in it, apparently.

V
--
Richard Herring
Apr 25 '07 #17

P: n/a
On Apr 25, 5:14 pm, Richard Herring <ju**@[127.0.0.1]wrote:
In message <1177147807.523762.146...@e65g2000hsc.googlegroups .com>,
James Kanze <james.ka...@gmail.comwrites
On Apr 20, 11:36 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
[... on explicitly writing what the compiler would do anyway]
And I do not agree that minimizing the number of functions is
arbitrary. It's definitely _better_.
Except that you don't minimize the number of functions. There
are exactly the same number of functions in both cases.
But there are more *user-written* functions which have to be maintained
when you add more data members. And the compiler is better at keeping
track of those members - in three different functions - than I am.
Any time you change the data members of the class, you have to
consider those functions, regardless of who wrote them. I don't
see where letting the compiler do it gains anything but less
keystrokes. And you end up with inlined functions, which isn't
necessarily a good idea.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 26 '07 #18

P: n/a
James Kanze wrote:
[..] I don't
see where letting the compiler do it gains anything but less
keystrokes.
Fewer keystrokes means fewer places where the programmer can screw
up. If you don't see any benefit in that, then nothing we can do
about that, unfortunately.
And you end up with inlined functions, which isn't
necessarily a good idea.
Could you elaborate on that, please?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 26 '07 #19

P: n/a
In message <11**********************@u32g2000prd.googlegroups .com>,
James Kanze <ja*********@gmail.comwrites
>On Apr 25, 5:14 pm, Richard Herring <ju**@[127.0.0.1]wrote:
>In message <1177147807.523762.146...@e65g2000hsc.googlegroups .com>,
James Kanze <james.ka...@gmail.comwrites
>On Apr 20, 11:36 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>[... on explicitly writing what the compiler would do anyway]
>And I do not agree that minimizing the number of functions is
arbitrary. It's definitely _better_.
>Except that you don't minimize the number of functions. There
are exactly the same number of functions in both cases.
>But there are more *user-written* functions which have to be maintained
when you add more data members. And the compiler is better at keeping
track of those members - in three different functions - than I am.

Any time you change the data members of the class, you have to
consider those functions, regardless of who wrote them.
Um. Really what you have to consider is (the semantics of) the _data
members_. If my coding standards insist that if a value class has more
than <some small numberdata members, they must all have standard
copy/assign/delete semantics (or be wrapped by something which does),
then I'm assured that the compiler-generated functions will do what's
necessary, and I don't have to look in three additional places to ensure
that all the data members are handled correctly.
I don't
see where letting the compiler do it gains anything but less
keystrokes. And you end up with inlined functions, which isn't
necessarily a good idea.
And it isn't necessarily a bad one.

--
Richard Herring
Apr 26 '07 #20

This discussion thread is closed

Replies have been disabled for this discussion.