Как мы знаем, основная проблема конструктора копирования по умолчанию заключается в том, что он выполняет поверхностное копирование.
Полное копирование вообще не является проблемой. Это проблема, только если вы хотите сделать глубокую копию, иметь ссылочный член и предположить, что неявный конструктор копирования делает то, что вы хотите.
Мелкое копирование часто бывает полезным и обычно преднамеренным.
но почему он не разыменовывает указатель и копирует содержимое?
Потому что, где конструктор копирования будет хранить скопированный объект? Куда должен указывать член-указатель?
Компилятор не может прочитать ваши мысли и не может знать, хотите ли вы выделить память или как выделить память. Если компилятор выделил память в неявной функции, то кто будет нести ответственность за ее удаление? Если компилятор неявно удаляет какие-либо указатели, было бы весьма удивительно, если вы намеревались иметь не принадлежащие указатели на то, что не должно быть удалено.
почему программист не может нести за это ответственность?
Управление памятью достаточно сложно. На данный момент этим можно управлять, следуя простому правилу: Ты delete
Все, что Ты new
. Если мы введем неявное распределение и возложим на программиста ответственность за знание существования этих неявных распределений, наша работа станет намного сложнее.
Кроме того, указатель может иметь недопустимое значение. В таких случаях косвенное обращение через него будет иметь неопределенное поведение. И невозможно проверить указатель, чтобы определить, является ли он недействительным. Это сделало бы предложенное неявное «глубокое копирование» чрезвычайно подверженным ошибкам.
Мелкое неявное копирование - единственный разумный выбор в языке, который имеет ручное управление памятью. Даже в языках со сборкой мусора это, как правило, лучший выбор.
, поэтому мы создаем свои собственные конструкторы копирования и не используем конструктор по умолчанию.
Мы редко пишут объявленные пользователем конструкторы копирования (за пределами курсов для начинающих). Они в основном нужны для классов, единственной целью которых является управление памятью (или другими ресурсами), такими как умные указатели. И нам редко нужно их писать, поскольку стандартная библиотека предлагает самые общие интеллектуальные указатели и структуры данных из коробки.
, мы должны создать наш собственный конструктор копирования, как только у нас будет динамическая память внутриclass
Действительно, если ваш класс управляет динамической памятью, ему понадобится специальный конструктор копирования. Но типичное решение - не управлять динамической памятью внутри вашего класса. Смотри параграф выше. Храните все и все выделения памяти и другие динамические ресурсы в интеллектуальном указателе или контейнере.