Copy Constructor in C++

This question already has an answer here:

  • What is The Rule of Three? 8 answers

  • 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.


    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.


    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.

    链接地址: http://www.djcxy.com/p/73184.html

    上一篇: 调用子类方法会导致分段错误

    下一篇: 在C ++中复制构造函数