Контрольный список для написания конструктора копирования и оператора присваивания в C ++ - PullRequest
18 голосов
/ 18 октября 2008

Пожалуйста, напишите список задач, которые конструктор копирования и оператор присваивания должны выполнить в C ++, чтобы сохранить безопасность исключений, избежать утечек памяти и т. Д.

Ответы [ 4 ]

15 голосов
/ 18 октября 2008

Сначала убедитесь, что вам действительно нужна поддержка копирования. В большинстве случаев это не так, и, таким образом, отключение обоих - это путь.

Иногда вам все равно необходимо обеспечить дублирование класса из полиморфной иерархии, в этом случае: отключите оператор присваивания, напишите (защищенный?) Конструктор копирования и предоставьте виртуальную функцию clone ().

В противном случае, если вы пишете класс значений, вы возвращаетесь в страну Ортогональной Канонической Формы Коплиена. Если у вас есть элемент, который не может быть просто скопирован, вам потребуется предоставить конструктор копирования, деструктор, оператор присваивания и конструктор по умолчанию. Это правило может быть уточнено, например: Закон Большой Двое

Я бы также рекомендовал взглянуть на C ++ FAQ по операторам присваивания , а также на идиому копирования и замены и GOTW .

4 голосов
/ 18 октября 2008

Версии, сгенерированные компилятором, работают в большинстве ситуаций.

Вам нужно немного подумать о проблеме, когда ваш объект содержит указатель RAW (аргумент за отсутствие указателей RAW). Итак, у вас есть указатель RAW, второй вопрос: владеете ли вы указателем (он был удален вами)? Если это так, то вам нужно будет применить правило 4.

Владение более чем 1 указателем RAW становится все труднее сделать правильно (увеличение сложности также не является линейным [но это наблюдение, и у меня нет реальной статистики, подтверждающей это утверждение]). Поэтому, если у вас есть более 1 RAW-указателя, подумайте о том, чтобы обернуть каждый в свой класс (в некоторой форме, умный указатель).

Правило 4: если объект является владельцем указателя RAW, вам нужно определить следующие 4 члена, чтобы убедиться, что вы правильно обрабатываете управление памятью:

  • 1010 * Конструктор *
  • Конструктор копирования
  • Оператор присваивания
  • Destructor

Как вы их определите, будет зависеть от ситуаций. Но стоит остерегаться:

  • Конструкция по умолчанию: установить указатель на NULL
  • Конструктор копирования: используйте идеал «Копировать и поменять», чтобы предоставить «Сильную гарантию исключения»
  • Оператор присваивания: проверка присвоения себе
  • Деструктор: защита от исключений, распространяющихся из деструктора.
1 голос
/ 06 ноября 2008

попробуйте прочитать это.

http://www.icu -project.org / документы / документы / cpp_report / the_anatomy_of_the_assignment_operator.html

- очень хороший анализ оператора присваивания

0 голосов
/ 18 октября 2008

Я понятия не имею об исключении, здесь безопасно, но я иду этим путем. Давайте представим, что это шаблонная оболочка массива. Надеюсь, это поможет:)

Array(const Array& rhs)
    {
        mData = NULL;
        mSize = rhs.size();
        *this = rhs;
    }

    Array& operator=(const Array& rhs)
    {
        if(this == &rhs)
        {
            return *this;
        }

        int len = rhs.size();

        delete[] mData;

        mData = new T[len];

        for(int i = 0; i < len; ++i)
        {
            mData[i] = rhs[i];
        }

        mSize = len;

        return *this;
    }
...