Skip to content

drdobbs C++ Made Easier: The Rule of Three

An Example and a Misconception

example code

NOTE:

1、原文给出的这个例子是非常具有代表性的。

这个例子,导致错误是double free,它的implicit defined copy constructor是shallow copy的

#include<iostream>
// This class contains a subtle error
class IntVec
{
public:
    IntVec(int n) :
                    data(new int[n])
    {
    }
    ~IntVec()
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        delete[] data;
    }
    int& operator[](int n)
    {
        return data[n];
    }
    const int& operator[](int n) const
    {
        return data[n];
    }

private:
    int *data;
};

int main()
{
    IntVec x(100);
    IntVec y = x;   // Trouble!
    return 0;
}
// g++ test.cpp -pedantic -Wall -Wextra

Fixing Our Class

Non-copyable

#include<iostream>
// This class contains a subtle error
class IntVec
{
public:
    IntVec(int n) :
                    data(new int[n])
    {
    }
    ~IntVec()
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        delete[] data;
    }
    int& operator[](int n)
    {
        return data[n];
    }
    const int& operator[](int n) const
    {
        return data[n];
    }

private:
    int *data;

    // these two member functions added
    IntVec(const IntVec&);
    IntVec& operator=(const IntVec&);
};

int main()
{
    IntVec x(100);
    IntVec y = x;   // Trouble! compile error
    return 0;
}
// g++ test.cpp -pedantic -Wall -Wextra

Rule of three

#include<iostream>
// This class corrects the error by
// defining copying and assignment
class IntVec
{
public:
    IntVec(int n) :
                    data(new int[n]), size(n)
    {
    }
    ~IntVec()
    {
        delete[] data;
    }
    ;
    int& operator[](int n)
    {
        return data[n];
    }
    const int& operator[](int n) const
    {
        return data[n];
    }

    IntVec(const IntVec &v) :
                    data(new int[v.size]), size(v.size)
    {
        std::copy(data, data + size, v.data);
    }
    IntVec&
    operator=(const IntVec &v)
    {
        int *newdata = new int[v.size];
        std::copy(v.data, v.data + v.size, newdata);
        delete[] data;
        data = newdata;
        size = v.size;
        return *this;
    }

private:
    int *data;
    int size;
};
int main()
{
    IntVec x(100);
    IntVec y = x;   // Trouble!
    return 0;
}
// g++ test.cpp -pedantic -Wall -Wextra