2

This is a general question that I've been asking for a while but couldn't get a clear answer to. Do I need to code a copy constructor for a class when all instance data fields in this class are standard built in C++ data types?

Ash
  • 61
  • 5
  • Are you using `new` ? If yes then yes you need the copy constructor and the assignment opeartor too. – DumbCoder May 05 '15 at 13:21
  • Maybe. The most common situation where it's necessary is where one of those "standard built in C++ data types" is a "pointer to T" (for some type T) and the object owns whatever the pointer points at. – Jerry Coffin May 05 '15 at 13:21

5 Answers5

6

The types of the member variables is not important for that(1), their semantics are. The rule is simple:

If you don't provide a copy constructor, the compiler will try to generate one for you. This default-generated one will perform the default copy operation on all member variables. For class types, this means calling the copy constructor. For primitive types, this means a bitwise copy.

If the default-generated constructor does what you need, don't declare your own. If it wouldn't do what you need, declare one yourself. It is possible to create a class with non-primitive member variables and perfectly OK default copy semantics:

struct PersonId
{
  std::string surname;
  std::vector<std::string> givenNames;
};

Likewise, it is possible to create a class with primitive-type member variables where the default copy semantics would not be OK:

class UniqueNamed
{
  int id;
  UniqueNamed() : id(0) {}

public:
  UniqueNamed(const UniqueNamed &src) : id(src.id + 1) {}

  int getId() const { return id; }

  static UniqueNamed initial;
};

So it depends on the class's semantics, not on the types of its data members.

This touches the general concept of the semantics of copying, moving & wonership, and their implementations in C++. You might want to read something about the rules of zero, three, and five.


(1) Of course, if any member variable is of a non-copyable type, and you want your class to be copyable, you have to provide the copy constructor yourself, as the default-declared one would be defined as deleted.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
3

If you don't code a copy constructor, there is a default one created that copy one by one each field of your class, calling their copy constructors if any.

For instance :

class Test {
public:
  int toto;
  char titi;
};

int main() {
    Test a;

    a.toto = 42;
    a.titi = 'a';
    Test b(a); // b will be initialized with same fields than a.

    return (0);
}

Be careful with this method: use it only on simple classes with, as you said, only fields from standard built in C++ data types.

The most common mistake here is when your class have a pointer field: The pointer is copied, but not reallocated, so you will have two instances of your class with a pointer on the same thing, and if one of them modify or delete it, the other one shall feel the consequences.

class Test {
public:
  std::string* field;

  Test() {
      field = new std::string("toto");
  }
  ~Test() {
      delete (field);
  }
};

int main () {
    Test a; // a.field is allocated.

    Test b(a); // b have the same pointer than a, as if you did b.field = a.field.
    // Here a and b destructors are called. They will delete the same pointers twice.
    // It will result as a segmentation fault.
    return (0);
}

Note: this is true for = operators as well if you don't overload it.

Aracthor
  • 5,757
  • 6
  • 31
  • 59
2

If you need the object to be copied by copying the value of each data member, then you don't need to write one; the implicitly generated one will do exactly that.

If you need something else to happen when you copy an object, or if something is preventing the implicit one from being generated (for example, a const data member) and you still want to be able to copy it, then you will need to write one.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

In general copy constructor is created by compiler for you. You need to create one /and assigment operator/ only when there are special objects or pointers inside the class, or you wish to have special handling or to define special checks or other special behavior. Example for such object that will require a user-defined copy constructor is a file. Other example why you need a user-defined copy constructor is that the default one will just copy data pointers. This means they will point same objects/same chunk of memory/. If the original object was on the stack, when it gets out of scope the destructor will free the pointer in the original object, and will leave you with pointer that points to invalid memory chunk and you will have segmentation fault.

-2

No, you don't if you are going to use it as POD (plain old data) object. Compiler will generate for you default copy constructor that behaves as you can expect it - just assigns all fields from one object to another.

antonpp
  • 2,333
  • 23
  • 28
  • 1
    What if the class has a pointer member? – rozina May 05 '15 at 13:23
  • @rozina, default copy constructor will treat pointers the same as other fields -- just copies their value. In some situations this is what you need, in others... well, that's why you can write your own constructor. – antonpp May 05 '15 at 13:27
  • 2
    So you answer is incorrect, since it states that you don't need to write your own copy constructor for POD types :) – rozina May 05 '15 at 13:29
  • 1
    @rozina, As I understand the terminology as soon as class has a user defined copy constructor it cannot be a POD class. So I don't really see my mistake. Maybe I should clarify the situations when you want "not default" behaviour (especially for pointers), but then it means that I didn't get the question right. Because as I thought OP asked what would happen if one doesn't write their own copy ctor and not about the problems related with this. – antonpp May 05 '15 at 13:39