12

I have a long class with a lot of data members. I want to write a copy constructor for it. But, if I write my own copy constructor, I lose access to the default copy constructor.

I just want to repair a few pointers in my own copy constructor. So I want to have a shallow copy of the object which can be done by the default copy constructor.

Is there a possibility to access the default copy constructor when I have my own copy constructor?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
pablo
  • 384
  • 2
  • 5
  • 17
  • 1
    How will other code know to call the default or your constructor? – mmmmmm Sep 14 '12 at 10:54
  • @Mark As I understand OP wants to use default ctor **inside** own ctor only. – Rost Sep 14 '12 at 10:56
  • @Mark: Ofc my copy constructor. I just want a shallow copy of the object before invocation of my copy contructor. Later I can do my own coping/fixing actions. – pablo Sep 14 '12 at 10:58
  • Could you illustrate with some short sample code how you could benefit from a default constructor being called in the copy constructor? – juanchopanza Sep 14 '12 at 11:28
  • @juanchopanza: The benefit is easy. I have shallow copy of an object and I don't have to do it by myself. – pablo Sep 17 '12 at 20:07
  • @pablo bot wouldn't you get the shallow copy anyway? – juanchopanza Sep 17 '12 at 20:17

8 Answers8

13

Wrap the things you don't want to change in a struct, and derive (privately) from it. In your copy constructor, simply invoke the copy constructor of your base class.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • The only thing I don't like about it is that it supports the questioner in what's probably folly: having "a few" pointers that need special treatment, in a single class. It does what was asked for, though. – Steve Jessop Sep 14 '12 at 11:10
  • 1
    @SteveJessop There are probably other criticisms one could make as well. Having a class with enough members to make this an issue, for example. As for the pointers... without knowing why they need special treatment, it's hard to be sure, but _if_ it's an issue of dynamically allocated objects and deep copy, then more than one pointer in any one class is a recipe for problems. – James Kanze Sep 14 '12 at 12:00
8

No you cannot have both default and your own copy c-tor.

But there are two workarounds with this problem:


1 Enclose your pointers in some class with defined copy semantics

Example:

class A {
public:
private:
   int trivial1;
   int trivial2;
   ...
   SomePointer  nontrivialMember;
};

class SomePointer {
public:
  SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
  int* nonTrivialMember;
};

2 Enclose the trivial parameters in some trivial structure

Example:

class A {
public:
   A(const A& o) : data(o.data) {
     // non trivial part
   }
private:
   struct Data {
     int trivial1;
     int trivial2;
     ...
   } data;
   int* nontrivialMember;
};

I would always select the first solution.

[UPDATE]

There is also 3rd solution, very similar to my second, enclose your trivial part in privately inherited base class. I'd still prefer the 1st solution.

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • 1
    So what is the motivation behind choosing the first solution – user877329 Jul 12 '15 at 07:57
  • 2
    @user877329 The main reason for selecting first is to implement only necessary copy/move semantics. By necessary I mean such which cannot be defined by compiler itself. In first solution you deal with pointer only. In the other solutions you must also copy this trivial part of a class. – PiotrNycz Jul 13 '15 at 07:51
4

The simplest approach to this would be to wrap up the pointers into classes that will perform the 'repair' manually in their copy constructor, then you can happily use the default copy constructor.

Keldon Alleyne
  • 2,103
  • 16
  • 23
0

No, there is no way to call the default copy constructor from an user defined copy constructor.

ronag
  • 49,529
  • 25
  • 126
  • 221
0

You can either use the default or your own, not both. If you want to choose different functionality for different objects you should just write a member function that handles that case.

void DeepCopy(MyClass* rhs);

For example.

Aesthete
  • 18,622
  • 6
  • 36
  • 45
0

You cannot access default copy ctor if you created your own - compiler just doesn't generate it. But ther is workaround - split you class into data structure and logic.

See example:

struct Data
{
  int i;
  std::string s;

  Data(): i(), s() {}
};

class Code: private Data
{
public:

  Code() {}

  Code(const Code& rhs): Data(rhs) // Call default copy ctor
  {
     i = 42; // Your copy part
     return *this;
  }

};
Rost
  • 8,779
  • 28
  • 50
0

My solution is a simple memcpy() instead of the impossible call to the implicit (compiler generated) copy constructor, as the example shown below:

Class Foo
{
public:
   ...
   Foo (Foo & other) {
      // copies trivial part (and non-trivial part with possible wrong values)
      memcpy(this, &other, sizeof(Foo));

      // your non-trivial part here, overwrites the wrong values (if any) above.
   }
}

Yet the side-effect is that the memcpy() will also copy those non-trivial part, which is a waste. If the non-trivial part does not contain too much space, I will prefer my solution.

For example, a class like below wastes only 4 byte copy of the one pointer, assuming the size of a pointer is 4 bytes.

Class Bar
{
    int x, y, z;

    // memcpy() wastes these 4 bytes copy,
    // since actual copy constructor wants a new string
    string *s;  
}
Robin Hsu
  • 4,164
  • 3
  • 20
  • 37
0

This worked for me... (C++11, don't know if it works on older std) Not sure why it doesn't end up in an endless loop.

class Foo {
public:
  Foo(const Foo &orig) {
     *this = orig;
     ... exchange pointers, do own stuff
  }
chhu79
  • 175
  • 2
  • 7
  • it doesn't end in an endless loop because `*this = orig` calls copy assignment, not copy ctor. – bolov Nov 09 '16 at 10:06
  • see http://stackoverflow.com/questions/2639017/calling-assignment-operator-in-copy-constructor on thoughts about this method – bolov Nov 09 '16 at 10:07
  • makes sense, thanks for the link! despite the mentioned cons I am in favor of the pro, but that really depends on the class... – chhu79 Nov 09 '16 at 13:36