Подтвердить что ты не робот

Использование std:: move с помощью std:: shared_ptr

У меня есть функция, определенная следующим образом:

void foo(std::shared_ptr<X> x) { ... };

Если я объявляю общий ptr X:

std::shared_ptr<X> sourcePtr(new X(...));

Затем я могу вызвать foo следующим образом:

foo(std::move(sourcePtr));

или

foo(sourcePtr);

Я понимаю, что если я использую первый вариант, то sourcePtr становится нулевым. Это также предотвращает увеличение счетчика ссылок?

Если это не имеет значения, какой вариант я должен предпочесть? Должен ли я рассматривать что-либо еще при принятии такого решения?

4b9b3361

Ответ 1

Да, если вы переместите общий указатель в функцию, то:

  • исходный sourcePtr станет нулевым, а

  • счетчик ссылок не изменяется.

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

Однако будьте осторожны, чтобы идентификатор sourcePtr оставался действительным для остальной части области, просто чтобы он содержал нулевой указатель. Это означает, что компилятор не будет жаловаться, если вы используете его после перемещения, но если вы забудете, что он был перенесен, вы, по всей вероятности, разыщите нулевое значение. Я часто использую эту "оптимизацию" move, и ее также несколько укусили: добавлена ​​функциональность, и если вы забудете отменить move, вы получите хороший авария.

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

Вышеприведенное предполагает, что существует код, который фактически использует sourcePtr между его объявлением и окончательным вызовом foo (благодаря @WhozCraig для указания его). Если этого не произойдет, вам гораздо лучше создать указатель прямо на сайте вызова:

foo(std::make_shared<X>(...));

Таким образом, вы сохраняете столько же атомных операций, и у вас нет потенциально опасного пустого общего указателя, лежащего вокруг.