Default assignment operator= in c++ is a shallow copy?

前端 未结 8 2141
挽巷
挽巷 2020-12-14 05:42

Just a simple quick question which I couldn\'t find a solid answer to anywhere else. Is the default operator= just a shallow copy of all the class\' members on the right ha

相关标签:
8条回答
  • 2020-12-14 06:19

    Yes, it just copies the object member-wise, which can cause issues for raw pointers.

    0 讨论(0)
  • 2020-12-14 06:19

    "shallow" versus "deep" copy is less meaningful in C++ than it is in C or Java.

    To illustrate this, I've changed your Foo class from three ints to an int, an int*, and a vector<int>:

    #include <iostream>
    #include <vector>
    
    class Foo {
    public:
      int a;
      int *b;
      std::vector<int> c;
    };
    
    using namespace std;
    
    int main() {
      Foo f1, f2;
      f1.a = 42;
      f1.b = new int(42);
      f1.c.push_back(42);
      f2 = f1;
    
      cout << "f1.b: " << f1.b << " &f1.c[0]: " << &f1.c[0] << endl;
      cout << "f2.b: " << f2.b << " &f2.c[0]: " << &f2.c[0] << endl;
    }
    

    When this program is run, it yields the following output:

    f1.b: 0x100100080 &f1.c[0]: 0x100100090
    f2.b: 0x100100080 &f2.c[0]: 0x1001000a0
    

    The int is boring, so I've left it out. But look at the difference between the int* and the vector<int>: the int* is the same in f1 and f2; it's what you would call a "shallow copy". The vector<int> however is different between f1 and f2; it's what you would call a "deep copy".

    What's actually happened here is that the default operator = in C++ behaves as if the operator = for all of its members were called in order. The operator = for ints, int*s, and other primitive types is just a byte-wise shallow copy. The operator = for vector<T> performs a deep copy.

    So I would say the answer to the question is, No, the default assignment operator in C++ does not perform a shallow copy. But it also doesn't perform a deep copy. The default assignment operator in C++ recursively applies the assignment operators of the class's members.

    0 讨论(0)
  • 2020-12-14 06:25

    I personally like the explanation in Accelerated c++. The text (page 201) says:

    If the class author does not specify the assignment operator, the compiler synthesizes a default version. The default version is defined to operate recursively - assigning each data element according to the appropriate rules for the type of that element. Each member of a class type is assigned by calling that member's assignment operator. Members that are of built-in type are assigned by assigning their values.

    As the members in the question are integers, I understand that they are deep copied. The following adaptation of your example illustrates this:

    #include<iostream>
    class foo {
    public:
      int a, b, c;
    };
    
    int main() {
        foo f1, f2;
        f1 = f2;
        std::cout << "f1.a and f2.a are: " << f1.a << " and " << f2.a << std::endl;
        f2.a = 0;
        std::cout << "now, f1.a and f2.a are: " << f1.a << " and " << f2.a << std::endl;
    }
    

    which prints:

    f1.a and f2.a are: 21861 and 21861
    now, f1.a and f2.a are: 21861 and 0
    
    0 讨论(0)
  • 2020-12-14 06:27

    I'd say, default operator= is a copy. It copies each member.

    The distinction between a shallow copy and a deep copy doesn't arise unless the members being copied are some kind of indirection such as a pointer. As far as the default operator= is concerned, it's up to the member being copied what "copy" means, it could be deep or shallow.

    Specifically, though, copying a raw pointer just copies the pointer value, it doesn't do anything with the referand. So objects containing pointer members are shallow-copied by default operator=.

    There are various efforts at writing smart pointers that perform clone operations on copying, so if you use those everywhere in place of raw pointers then the default operator= will perform a deep copy.

    If your object has any standard containers as members, then it may be confusing to (for example) a Java programmer to say that operator= is a "shallow copy". In Java a Vector member is really just a reference, so "shallow copy" means that Vector members aren't cloned: source and destination refer to the same underlying vector object. In C++ a vector member will be copied, along with its contents, since the member is an actual object not a reference (and vector::operator= guarantees the contents are copied with it).

    If your data member is a vector of pointers, then you don't have either a deep copy or a shallow copy. You have a semi-deep copy, where the source and destination objects have separate vectors, but the corresponding vector elements from each still point to the same, uncloned object.

    0 讨论(0)
  • 2020-12-14 06:28

    No. operator= doesn't perform a copy at all. It's an assignment operator, not copy operator.

    The default assignment operator assigns each member.

    0 讨论(0)
  • 2020-12-14 06:34

    If a, b and c were classes then the assignment operator for those classes would be called, so the compiler isn't simply copying the raw memory contents - but as others pointed out, any raw pointers will be copied without any attempt to duplicate the pointed-to thing, thus giving you the potential for dangling pointers.

    0 讨论(0)
提交回复
热议问题