473,756 Members | 1,818 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Avoid automatic copy constructor generation

Hi,

is there a way to avoid the automatic copy constructor generation. I do
not want the object to be non-copyable. I simply do not want that
copying is done by the default copy constructor. But there is a
constructor that accepts the base class. This one should be used for
copying.

In fact i have a set of classes with a common abstract base. The
implementations do not have own data members. They only implement
different functionality. But is makes sense to do assignments and copy
construction between these set of types. This effectively changes the
functionality depending on the current type.
class ContainerBase
{ // ...
};

class Container1
: public ContainerBase
{ // no own data members!
public:
Container1()
{}
Container1(cons t ContainerBase& r)
: ContainerBase(r )
{}
Container1& operator=(const ContainerBase& r)
{ ContainerBase:: operator=(r); return *this; }
};

class Container2
: public ContainerBase
{ // no own data members!
public:
Container2()
{}
Container2(cons t ContainerBase& r)
: ContainerBase(r )
{}
Container2& operator=(const ContainerBase& r)
{ ContainerBase:: operator=(r); return *this; }
};
int main()
{ Container1 c1;
Container2 c2 = c1; // OK
Container1 c3 = c1; // Wrong! Invokes Container1(cons t Contarine1& r)
return 0;
}
Of course, I could implement the copy constructors to do the same thing
as the constructor from const ContainerBase&. But this is really
unneeded redundancy. And the copy constructor is much more complicated
in the real application than in this small example. Furthermore the auto
generated copy constructor is unusable. It has undefined behavior
because of some special internal storage dependencies. It also has to do
with multiple inheritance, so I could not move the code to a member
function either.

Is there a way to avoid the required redefinition of the copy
constructor for each class?
Marcel
Oct 25 '08
34 3683
Erik Wikström wrote:
On 2008-10-27 19:29, Jeff Schwab wrote:
>Juha Nieminen wrote:
>>Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopya ble.

Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopya ble is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?
It may be a hack, but it's an idiomatic one that's been used since the
epoch of C++.

I don't consider it to be a hack, but an aid to documentation. The
reader can tell at a glance that the class isn't copyable. It also
saves typing!

--
Ian Collins
Oct 27 '08 #21
Pete Becker wrote:
>If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automaticall y copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)

So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?
No, you first call the compiler-generated copy constructor, and then
you copy the special members appropriately.

For example, if you had, let's say, a pointer to a dynamically
allocated object, the compiler-generated copy constructor would simply
copy the value of the pointer, so the copy would point to the same
dynamically allocated object. However, that doesn't matter: Once it has
done that, you simply make a deep copy of the object (or whatever) and
make the pointer point to that new object.

The idea is that you only need to write this special copying code for
that one pointer, and you don't need to write anything for any of the
other member variables (because those are handled by the
compiler-generated copy constructor).
Oct 27 '08 #22
Ian Collins wrote:
Erik Wikström wrote:
>On 2008-10-27 19:29, Jeff Schwab wrote:
>>Juha Nieminen wrote:
Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopya ble.
Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopy able is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?
It may be a hack, but it's an idiomatic one that's been used since the
epoch of C++.

I don't consider it to be a hack, but an aid to documentation. The
reader can tell at a glance that the class isn't copyable. It also
saves typing!
Agreed. It's self-documenting, and doesn't require the reader to be
familiar with yet another language feature.
Oct 27 '08 #23
On 2008-10-27 18:03:07 -0400, Juha Nieminen <no****@thanks. invalidsaid:
Pete Becker wrote:
>>If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automatical ly copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)

So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?

No, you first call the compiler-generated copy constructor, and then
you copy the special members appropriately.
Okay, you copy the special members twice.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 27 '08 #24
Jeff Schwab wrote:
> One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to your
class, you have to remember to add it to the copy constructor (and
assignment operator). This is extremely easy to forget.

You have a reasonable point, but IMO such a class is already responsible
for too many things. If a member requires special handling during
copying, then it can be wrapped in a class whose copy constructor does
the right thing. That special handling should be the wrapper's only
job.
That's a reasonable design. On one hand it simplifies the outer class,
because you don't have to write a copy constructor for the entire class.
On the other hand it adds a small layer of complexity to that special
member. For example assume you have something like this:

class MyClass
{
std::list<Objec tobjectList;
std::list<Objec t>::iterator currentObject;
...
};

Let's assume the specification of this code is that 'currentObject'
always points to either an object inside 'objectList', or to
objectList.end( ).

This class requires a copy constructor and assignment operator if
instances of this class must be copyable. The copy constructor and
assignment operator need to make 'currentObject' to point to the copied
list (rather than the original).

By your suggested design both 'objectList' and 'currentObject' need to
be wrapped inside an inner class if we want to avoid having to write a
copy constructor and assignment operator on the outer class, so it would
become something like:
class MyClass
{
struct ObjectList
{
std::list<Objec tobjectList;
std::list<Objec t>::iterator currentObject;

ObjectList(cons t ObjectList&); // Implement these appropriately
ObjectList& operator=(const ObjectList&);
};

ObjectList objectList;
...
};

Now accessing the 'objectList' member has to always be done with a
"objectList.obj ectList" (or whatever we want to call the struct
instantiation). Well, I suppose that's a small price to pay for not
having to write a copy constructor and assignment operator for the outer
class...
Oct 27 '08 #25
Pete Becker wrote:
Okay, you copy the special members twice.
Basically yes. The alternative is the current one: You have to copy
everything explicitly.
Oct 27 '08 #26
On Oct 27, 2:05 am, Pete Becker <p...@versatile coding.comwrote :
On 2008-10-26 17:37:53 -0400, Ian Collins <ian-n...@hotmail.co msaid:
Pete Becker wrote:
On 2008-10-25 21:55:54 -0400, Victor Bazarov
<v.Abaza...@com Acast.netsaid:
>Juha Nieminen wrote:
Marcel Müller wrote:
is there a way to avoid the automatic copy constructor
generation .
>>Yes: Implement your own copy constructor. That will make
the compiler to not to create a default one.
>You don't have to implement it. Just declare one. If
your program does not use it, you don't have to define it.
And to make sure the program does not use it, declare it
'private'.
And a note for the future: with C++0X you don't need to
declare it private.
class C
{
public:
C(const C&) = delete;
};
The "= delete" says that it doesn't exist. There's also "=
default", to tell the compiler to generate the default
version even if it wouldn't otherwise. These also apply to
default constructors, generated assignment operators, etc.
I can see the benefit of "= default", but what benefits does
"= delete" offer over private constructors?
A bit of clarity. A private constructor can be implemented,
and used by members and friends. "= delete" says it doesn't
exist.
And can't be used even by members and friends.

Not a big thing, but the fact that you cannot copy an object is
part of the public interface. So the fact that you explicitly
say so should logically appear in the public part of the class
definition.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 28 '08 #27
In message <Ga************ ***@read4.inet. fi>, Juha Nieminen
<no****@thanks. invalidwrites
>Pete Becker wrote:
>Okay, you copy the special members twice.

Basically yes. The alternative is the current one: You have to copy
everything explicitly.
How do you handle reference members?

--
Richard Herring
Oct 28 '08 #28
On Oct 27, 10:20 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
On 2008-10-27 19:29, Jeff Schwab wrote:
Juha Nieminen wrote:
Ian Collins wrote:
I can see the benefit of "= default", but what benefits
does "= delete" offer over private constructors?
Declaring a constructor private is more a hack than a clean
idiom. If you accidentally call the copy constructor from
the class itself, you will not get a clean compiler error,
but an obscure linker error, which is not really the best
possible solution.
That's true if the private constructors are declared
directly in the non-copyable class. I wonder whether
=delete offers anything over EBO/inheritance-based utilities
like boost::noncopya ble.
Elegance and simplicity. A private copy-constructor is a hack
but boost::noncopya ble is much worse, a complex solution to a
simple problem. Why should I have to inherit from some other
class just to make my class non-copyable?
Documentation. Inheritance defines an isA relationship. Your
class isA UncopiableObjec t.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 28 '08 #29
On Oct 27, 11:03 pm, Jeff Schwab <j...@schwabcen ter.comwrote:
Ian Collins wrote:
Erik Wikström wrote:
On 2008-10-27 19:29, Jeff Schwab wrote:
Juha Nieminen wrote:
Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "=delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom.If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopya ble.
Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopya ble is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?
It may be a hack, but it's an idiomatic one that's been used
since the epoch of C++.
I don't consider it to be a hack, but an aid to
documentation. The reader can tell at a glance that the
class isn't copyable. It also saves typing!
Agreed. It's self-documenting, and doesn't require the reader
to be familiar with yet another language feature.
Yes and no. I used the techique back in the early 1990's. I
dropped it for awhile because readers weren't familiar with it.
The private copy constructor was the standard idiom, which they
immediately recognized, where as they didn't know what
UncopiableObjec t did; at the time, at least, it didn't occur to
them that a base class might have not direct interface, and they
expected something more. Thanks to things like std::iterator<> ,
std::unary_func tion<>, etc., modern C++ programmers are far more
open about this, and when they see a class called
UncopiableObjec t, they don't expect anything more than that it
can't be copied. Some I've reverted to doing things the way I
did 25 years ago.

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

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2901
by: puzzlecracker | last post by:
From my understanding, if you declare any sort of constructors, (excluding copy ctor), the default will not be included by default. Is this correct? class Foo{ public: Foo(int); // no Foo() is included, i believe. };
0
9456
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10034
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9872
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9843
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7248
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5142
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5304
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3805
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3358
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.