2016-11-02 7 views
2

Давайте предположим, что у нас есть что-то вроде этого:Конструктор: unique_ptr + движение против shared_ptr

struct Complex{ 
    Complex(Part1 p1, Part2 p2, Part3 p3) 
} 

Part1 p1; 
Part2 p2; 
Part3 p3; 

Однако прохождение копий не является эффективным, так что мы должны двигаться к указателям. Вопросы, какой тип использовать — unique_ptr или shared_ptr

На первый взгляд, так как Complex является реальным владельцем p1, p2, p3, кажется unique_ptr лучше; однако, поскольку он не может быть скопирован, нам нужно будет использовать std::move.

Так что мой вопрос —, что это лучший способ для этого случая, создать unqiue_ptr из Part, а затем использовать move в Complex «s конструктора, или создать shared_ptr из самого начала и использовать shared_ptr вместо этого?

+0

* Однако передача копий неэффективна, поэтому нам нужно перейти к указателям. * Или вы сделаете сложность и часть движимыми? – stijn

+0

Комплекс - это просто сложный, долгоживущий объект. Но на текущий момент я не планирую реализовывать «правило пяти». –

+2

Также нет, если это решение вашей проблемы? В любом случае: умные указатели представляют собой своеобразное владение, поэтому ответ кажется простым: если p1/p2/p3 не * shared *, не используйте * shared * _ptr? – stijn

ответ

9

Лучшим решением было бы сделать типы Part дешевыми для перемещения и перемещать их. Однако, если это не вариант, вам придется прибегать к управлению ими динамически.

Как вы говорите, Complex владеет частями, поэтому он должен принимать их как std::uniqe_ptr<Part> и перемещать эти указатели в себя. Перемещение std::unique_ptr грязно дешево: возможно, это всего лишь два назначения указателя.

С другой стороны, используя std::shared_ptr и копирование, что включает в себя ненужное атомного приращения (для создания копии) и декремента (для уничтожения оригинала). Атомные операции, безусловно, далеки от дешевых для современных многоядерных процессоров.

Так что просто придерживайтесь намеченной семантики вашего кода (уникальная собственность, которая идиоматически выражается std::unique_ptr), и вы получите хорошую производительность в качестве бонуса.

+0

Почему два назначения указателя, а не один? – GeorgeAl

+1

@GeorgeAl Один, чтобы указать пункт назначения к пункту, и один, чтобы указать источник на нуль. В противном случае деструктор источника не знал бы, что он пуст, и освободит переводчика. – Angew