Какой тип указателя мне следует передать методу в C ++ 11? - PullRequest
5 голосов
/ 15 февраля 2012

У меня есть два разных сценария:

  1. У вас есть shared_ptr
  2. У вас есть unique_ptr

ответ может быть таким же.

Рассмотрим метод, который использует указатель, но не предполагает владения:

void use_pointer(T ptr)
{
    ptr->act();
}

Должно ли T быть

  • my_type * (необработанный указатель)
  • const shared_ptr<my_type> & (отправка const ref, если используется shared_ptr)
  • const unique_ptr<my_type> & (отправка const ref, если используется unique_ptr)
  • weak_ptr<my_type>(конструирование уязвимости для вызова метода)

Что-то еще?Спасибо!

Ответы [ 5 ]

10 голосов
/ 15 февраля 2012

Если вы не вступаете в права собственности, то желательно принять ссылку на pointee. Если вы хотите выразить необязательность, вы можете использовать необработанный указатель, или вы можете использовать, например, boost::optional<U&> (где U тип pointee).

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

5 голосов
/ 15 февраля 2012

Пусть вызывающая сторона решит:

template<typename T>
void use_pointer(const T& ptr)
{
    ptr->act();
}

Прекрасно работает с необработанными указателями (если вызывающая сторона имеет, например, массив с автоматическим или статическим временем жизни), shared_ptr, unique_ptr, а такжевсевозможные типы итераторов, если вызывающая сторона передает вам один элемент из коллекции.

3 голосов
/ 15 февраля 2012

В этом случае, вероятно, должно быть my_type&. Если вам действительно нужно передать указатель, просто передайте необработанный: так как вы используете умные указатели в своем коде, когда кто-то видит необработанный указатель, он не должен думать: «О, нет, он может просочиться!» а скорее «ага, не владеющий указателем» (то есть, если они знакомы с идиоматическим C ++).

0 голосов
/ 15 февраля 2012

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

0 голосов
/ 15 февраля 2012

Невозможно ответить на вопрос, не зная, почему у вас есть умный указатель (вместо необработанного указателя) и не зная семантика вызываемой функции, и в частности, почему она нуждается в указатель (а не вызов по значению или по константной ссылке). Как хороший отправная точка, однако: если функция принимает тип класса, используйте const ссылка, в противном случае используйте значение. (Но есть ли сценарий, когда у вас есть указатель на что-то, что не является типом класса?)

...