Конструктор копирования сначала копирует указатель, а затем разыменовывает его для получения «глубокой» копии - PullRequest
0 голосов
/ 05 января 2019

Я смотрю на следующий (плохой) пример кода в http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c22-make-default-operations-consistent:

class Silly {   // BAD: Inconsistent copy operations
    class Impl {
        // ...
    };
    shared_ptr<Impl> p;
public:
    Silly(const Silly& a) : p{a.p} { *p = *a.p; }   // deep copy
    Silly& operator=(const Silly& a) { p = a.p; }   // shallow copy
    // ...
};

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

Имеет ли смысл конструктор "глубокого копирования"? Похоже, что при входе в тело, p будет таким же, как a.p, и самоопределение ничего не делает (в лучшем случае).

Я что-то упустил?

Ответы [ 2 ]

0 голосов
/ 05 января 2019
Silly(const Silly& a) : p{a.p} { *p = *a.p; }

В дополнение к копированию лежащего в основе shared_pointer создаст копию значения, указанного им. Меня беспокоит то, что shared_ptr<T>::operator* на самом деле возвращает T&, поэтому наше назначение изменит значение для блока управления и фактически ничего не выполнит.

Но опять же, целью было не продемонстрировать фактическое глубокое копирование, а обеспечить несогласованные операции копирования.

Глубокая копия shared_ptr будет выглядеть так

Silly(const Silly& a) : p{make_shared<Impl>(*a.p)} {}
0 голосов
/ 05 января 2019

Действительно, это просто чепуха.

Предположительно, в этом суть примера, хотя я не уверен, что это отличный пример.

В противном случае авторы имели в виду:

Silly(const Silly& a) : p{std::make_shared<Impl>()} { *p = *a.p; }

или

Silly(const Silly& a) : p{std::make_shared<Impl>(*a.p)} {}

Или что-то подобное.

...