c++

Copy Constructor

For a Function Area(), argument passed is copied:

1
Double Area(double radius);

So, when invoking Area(), argument is copied to parameter ‘radius’, the rule can also be used in ‘object’(instance of class)

  • Shallow copy and its problems

    There is a ‘new’ and there is a ‘delete’

    But now I wanna copy the object, in the same time, we copied its pointer member, but we have no way to copy the buffer area that the pointer pointed, which will result in two objects point one memory allocated dynamically. When you destroy one of them, <delete[]> wile release the memory block, cause the copy of pointer that another object stored invalid. THIS is called Shallow Copy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Mystring 
{
private:
char* buffer;
public:
Mystring(const char* inistString) //Constructor
{
if(initString != NULL)
{
buffer = new char(strlen(initString) + 1); //Allocating memory
strcpy(buffer, initString);
}
else
buffer = NULL;
}
~Mystring() //Destructor
{
cout << "invoking destructor, clearing up" << end;
if(buffer != NULL)
delete [] buffer;
}

int GetLength()
{
return strlen(buffer);
}

const char* GetString()
{
return buffer;
}
};
//Use function rather than int func
void UseMyString(MyString str)
{
cout << "String buffer in sayHello is "<< str.GetLength();
cout << " characters long"<< endl;

cout << "buffer contains: "<< str.GetString()<<endl;
return;
}
int main()
{
MyString sayHello("Hello from String class");
UseMyString(sayHello);

return 0;
}
1
2
3
4
5
6
//OutPut:
///String buffer in MyString is 23 characters long
//buffer contains: Hello from String Class
//Invoking destructor, clearing up
//Invoking destructor, clearing up
//<crash as seen in screen>
  • Make sure deep copy

    1
    2
    3
    4
    5
    6
    7
    8
    class MyString
    {
    MyString (const MyString& copySource); //copy constructor
    MyString (const MyString copySource)
    {
    //Copy constructor implementation code
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    class Mystring 
    {
    private:
    char* buffer;
    public:
    Mystring(const char* inistString) //Constructor
    {
    buffer = NULL;
    cout << "Default constructor: creating new MyString" << endl;
    if(initString != NULL)
    {
    buffer = new char(strlen(initString) + 1); //Allocating memory
    strcpy(buffer, initString);

    cout << "buffer points to: 0X"<<hex;
    cout << (unsigned int*)buffer <<endl;
    }
    }

    MyString(const MyString & copySource)//copy constructor
    {
    buffer = NULL;
    cout << "Copy constructor: copying from MyString" << endl;
    if(copySource.buffer != NULL)
    {
    //allocate own buffer
    buffer = new char [strlen(copySource.buffer) + 1];

    //deep copy from the source into local buffer
    strcpy(buffer, copySource.buffer);
    cout << "buffer points to: 0X" <<hex;
    cout << (unsigned int*)buffer << endl;
    }
    }

    ~Mystring() //Destructor
    {
    cout << "invoking destructor, clearing up" << end;
    if(buffer != NULL)
    delete [] buffer;
    }

    int GetLength()
    {
    return strlen(buffer);
    }

    const char* GetString()
    {
    return buffer;
    }
    };
    //Use function rather than int func
    void UseMyString(MyString str)
    {
    cout << "String buffer in sayHello is "<< str.GetLength();
    cout << " characters long"<< endl;

    cout << "buffer contains: "<< str.GetString()<<endl;
    return;
    }
    int main()
    {
    MyString sayHello("Hello from String class");
    UseMyString(sayHello);

    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //Output:
    //Default constructor
    //buffer points to:
    //copy constructor: copying from MyString
    //buffer points to:
    //String buffer in MyString is 17 characters long
    //buffer containsL Hello from String Class
    //Invoking destructor, clearing up
    //Invoking destructor, clearing up
    • What you should do:

      • Class contains Primitive pointer menmber(char*), you must write Copy constructor and Copy assignment operator.

      • When writing Copy constructor, you must make the parameter that accept source object is declared as a ‘const’ reference.

      • When declaring constructor you must consider using keyword ‘explicit’, which will avoid implicit conversation.

      • You must declare class members to std::String-like and Smart pointer class(rather than Primitive pointer), cause that the constructor is implemented, which can help you work easier.

        • What you shouldn’t do

          Do not declare class members as Primitive pointer.

Share