Object Copy

Copy in C

Copy of objects in C: struct

struct point
{
    int x;
    int y;
};
struct point p1 = {2,7};
struct point p2;

p2 = p1;
  • struct point: memberwise copy

  • Simple: transfer of memory image

Copy Constructor

Copying objects in C: similar to C++

class point
{
    // ...
};
...
point p1;
point p2(p1);
  • Compiler generates copy constructor

  • ⟶ member by member

  • ⟶ simple data types just as in C

But …

Copy Constructor and Pointer Members (1)

Caution, Trap: pointer members

class String
{
public:
    String(const char *c_str);
private:
    char *_c_str;
};
String s1("hello");
String s2 = s1; // ctor!
../../../../../../_images/02-02-00-pointer-member.svg

Copy Constructor and Pointer Members (2)

Segmentation Fault in the best of all cases …

  • Pointer member is to compiler simply a pointer

  • Pointers are copied

  • But not what they point to

  • The first of both objects that is destroyed frees memory

  • How should the compiler know!

../../../../../../_images/02-02-00-pointer-member-segfault.svg

Copy Constructor and Pointer Members (3)

Solution

  • Explicit copy constructor

  • Copy the memory pointed to

String::String(const String& s)
{
    _c_str = new char[
         strlen(s._c_str)+1];
    strcpy(_c_str, s._c_str);
}
../../../../../../_images/02-02-00-pointer-member-2.svg

Copy Constructor: Recursive/Memberwise

struct TwoStrings
{
    String s1;
    String s2;
};
struct TwoTwoStrings
{
    TwoStrings s21;
    TwoStrings s22;
};
  • String has copy constructor (correct because handwritten)

  • TwoStrings is correct

  • TwoTwoStrings is correct

  • ⇒ …

Assignment Operator

Second way of copying objects: overwrite an existing object

class point
{
    // ...
};

point p1, p2;
// ...
p2 = p1; // assignment!
  • Like Copy Constructor generated by compiler

  • ⟶ Member by member

  • ⟶ simple data types just as in C

But …

  • As with the copy constructor ⟶ pointer members!

  • Assignment operator is best self defined when pointer members are involved

Assignment Operator and Pointer Members: Memory Leak

Caution, naively buggy!

String& String::operator=(
    const String& s)
{
    _c_str = new char[
        strlen(s._c_str)+1];
    strcpy(_c_str, s._c_str);
    return *this;
}

String s1("hello");
String s2("hallo");
s2 = s1;     // LEAK!
../../../../../../_images/02-02-00-pointer-member-assignment-operator.svg

Assignment Operator and Pointer Members: Memory Leak, Straighforward Fix

Caution, still naively buggy!

String& String::operator=(
    const String& s)
{
    delete[] _c_str;        // BUG!!
    _c_str = new char[
        strlen(s._c_str)+1];
    strcpy(_c_str, s._c_str);
    return *this;
}

WTF, why could this be a bug??

Assignment Operator and Pointer Members: Self-Assignment

Correct nonsense …

  • Why would somebody want to write this?

  • But anyway, it is legal!

int i = 42;
i = i;
String s("hello");
s = s;      // SEGFAULT!! (if you're lucky)
  • Self Assignment

  • Rare but true!

  • User expects that this is not an error

Assignment Operator: Self Assignment, Correctly Implemented

Ultimate Fix: Self Assignment Check

String& String::operator=(
    const String& s)
{
    if (this != &s)} {        // SELF ASSIGNMENT CHECK!!
        delete[] _c_str;
        _c_str = new char[
            strlen(s._c_str)+1];
        strcpy(_c_str, s._c_str);
    }
    return *this;
}