2016-09-19 5 views
2

Предположим, у меня есть класс, который Foo «имеет» одну переменную-член, который является указателем на какой-то другой объект Bla:Как правильно обращаться с возвращаемыми значениями объектов с указателями?

struct Foo { 
    Bla *bla; 

    Foo() { 
     this->bla = new Bla(); 
    } 
    ~Foo() { 
     delete this->bla; 
    } 
}; 

Как справиться с возвратом по значению таких объектов?

Foo make_foo() { 
    return Foo(); 
} 

Это создает новый Foo и Bar, возвращают копию созданного объекта Foo включая копию внутреннего указателя, а затем разрушают локальный объект и с ним Bla объекта. Таким образом, следующий код не сработает:

Foo f = make_foo(); 
std::cout << f.bla << std::endl; 

В настоящее время это считается плохой дизайн?

Должен ли я предоставить copy constructor? В этом случае глубокие копии более сложных деревьев объектов могут иметь серьезные последствия для производительности.

Должен ли я предоставить move constructor? Будет ли это правильно обрабатывать указатель bla?

+0

Почему, по вашему мнению, код не удается? 'bla' также копируется (сам указатель). Возможно, вам захочется увидеть [Что такое правило трех?] (Http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). – songyuanyao

+1

Если это необходимо, для вашего конструктора копирования также существует [copy-on-write] (http://stackoverflow.com/questions/628938/what-is-copy-on-write), что может снизить влияние вашей производительности. Поделитесь некоторыми ссылками подсчитанных копий 'bla' (например, используйте [' shared_ptr'] (http://en.cppreference.com/w/cpp/memory/shared_ptr)), затем не делайте глубокую копию, пока не на самом деле необходимо изменить данные. –

ответ

2

Поскольку ваш класс выделяет динамическую память и освобождает память в деструкторе, следуйте The Rule of Three. Предоставьте конструктор копирования и оператор присваивания копии.

Если вы понимаете семантику перемещения или собираетесь использовать ссылки rvalue, укажите конструктор перемещения и переместите оператор присваивания. См. Rule-of-Three becomes Rule-of-Five with C++11? для получения дополнительной информации.

+0

Отличные ссылки на * Правило трех *, спасибо! – Jens