Почему CPP не создает конструктор глубокой копии по умолчанию? - PullRequest
0 голосов
/ 10 октября 2019

Я не понимаю, почему у них нет конструктора копирования, который делает реальное кратное оригинала.

Как мы знаем, основная проблема конструктора копирования по умолчанию заключается в том, что он выполняет поверхностную обработку. копировать. Таким образом, если указатель существует, он будет копировать только его адрес, но почему он не разыменовывает указатель и копирует содержимое? Основная проблема возникает при наличии динамического распределения памяти. Чтобы можно было по ошибке удалить его, указав на него указатель, поэтому мы создаем свои собственные конструкторы копирования и не используем его по умолчанию.

Но я не могу понять, почему не CPPсделай это? Почему он не копирует содержимое

Ответы [ 3 ]

9 голосов
/ 10 октября 2019

Как мы знаем, основная проблема конструктора копирования по умолчанию заключается в том, что он выполняет поверхностное копирование.

Мы этого не знаем.

именно поэтому мы создаем наши собственные конструкторы копирования и не используем конструктор по умолчанию.

В C ++ вы почти никогда не должны писать свой собственный конструктор копирования ( правило нуля ).

Основная проблема возникает при динамическом распределении памяти. Так что можно ошибочно удалить его, указав на него указатель

Это не проблема. Почему? Потому что в C ++ мы используем концепцию RAII и у нас есть инструменты в стандартной библиотеке, которые решают все проблемы, которые вы видите. В C ++ вам никогда не придется писать явное new, и у вас никогда не должно быть необработанного указателя, который является владельцем. Используйте стандартные контейнеры (например, std::vector) и интеллектуальные указатели, например (std::unique_ptr).

Я не понимаю, почему у них нет конструктора копирования, который делает реальное кратное оригинала

Поскольку компилятор не знает, какой должна быть семантика копирования объекта. Это знает только автор класса. Вы не можете знать, какова семантика указателя. Является ли указатель, который уникально владеет ресурсом памяти? Если да, было ли это приобретено с malloc, new, new[] или с чем-то еще? Разделяет ли он свое владение памятью? Или это просто указывает на объект, которому он не принадлежит? Поскольку вы не можете знать ничего из этого из объявления / определения класса, компилятор просто не может автоматически реализовать «глубокое копирование» с необработанными указателями.

За исключением , он делает . Он реализует глубокое копирование по умолчанию, или поверхностное копирование по умолчанию, или их комбинацию. И это так правильно. Помните, когда я говорил вам не использовать сырые указатели для владения? Используйте соответствующие абстракции (контейнеры, умные указатели), и ctor по умолчанию будет делать именно то, что ему нужно.

4 голосов
/ 10 октября 2019

Как мы знаем, основная проблема конструктора копирования по умолчанию заключается в том, что он выполняет поверхностное копирование.

Полное копирование вообще не является проблемой. Это проблема, только если вы хотите сделать глубокую копию, иметь ссылочный член и предположить, что неявный конструктор копирования делает то, что вы хотите.

Мелкое копирование часто бывает полезным и обычно преднамеренным.

но почему он не разыменовывает указатель и копирует содержимое?

Потому что, где конструктор копирования будет хранить скопированный объект? Куда должен указывать член-указатель?

Компилятор не может прочитать ваши мысли и не может знать, хотите ли вы выделить память или как выделить память. Если компилятор выделил память в неявной функции, то кто будет нести ответственность за ее удаление? Если компилятор неявно удаляет какие-либо указатели, было бы весьма удивительно, если вы намеревались иметь не принадлежащие указатели на то, что не должно быть удалено.

почему программист не может нести за это ответственность?

Управление памятью достаточно сложно. На данный момент этим можно управлять, следуя простому правилу: Ты delete Все, что Ты new. Если мы введем неявное распределение и возложим на программиста ответственность за знание существования этих неявных распределений, наша работа станет намного сложнее.

Кроме того, указатель может иметь недопустимое значение. В таких случаях косвенное обращение через него будет иметь неопределенное поведение. И невозможно проверить указатель, чтобы определить, является ли он недействительным. Это сделало бы предложенное неявное «глубокое копирование» чрезвычайно подверженным ошибкам.

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

, поэтому мы создаем свои собственные конструкторы копирования и не используем конструктор по умолчанию.

Мы редко пишут объявленные пользователем конструкторы копирования (за пределами курсов для начинающих). Они в основном нужны для классов, единственной целью которых является управление памятью (или другими ресурсами), такими как умные указатели. И нам редко нужно их писать, поскольку стандартная библиотека предлагает самые общие интеллектуальные указатели и структуры данных из коробки.

, мы должны создать наш собственный конструктор копирования, как только у нас будет динамическая память внутриclass

Действительно, если ваш класс управляет динамической памятью, ему понадобится специальный конструктор копирования. Но типичное решение - не управлять динамической памятью внутри вашего класса. Смотри параграф выше. Храните все и все выделения памяти и другие динамические ресурсы в интеллектуальном указателе или контейнере.

1 голос
/ 10 октября 2019

Компилятор не имеет возможности узнать значение указателей, которые он должен «глубоко копировать».

Например, указатель с плавающей точкой указывает на один float или массив float в стиле C? Если это массив, какова длина массива, который он должен копировать? Обратите внимание, что я не говорю о массивах в стиле C ++ (то есть std :: array).

Если вы хотите, чтобы «глубокое копирование» выполнялось автоматически, вы можете использовать контейнерные классы для данныхчлены, которые должны быть скопированы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...