Полезно ли передавать функции std :: weak_ptr? - PullRequest
0 голосов
/ 03 декабря 2018

Я читал эту статью Херба Саттера о передаче умных указателей на функции.Он не упоминает std::weak_ptr, и, честно говоря, я не могу найти хороший сценарий, в котором передача такого умного указателя полезна.

Принимает ли функция ответственность?Пропуск std::shared_ptr.Должна ли функция просто работать с базовым объектом?Передайте необработанный указатель или ссылку.

Таким образом, передача std::weak_ptr функциям на 100% бесполезна?

Ответы [ 3 ]

0 голосов
/ 03 декабря 2018

Итак, передается ли std::weak_ptr функциям, которые на 100% бесполезны?

Нет.

Рассмотрим этот пример с игрушкой.

struct PointerObserver
{
    std::weak_ptr<int> held_pointer;

    void observe( std::weak_ptr<int> p )
    {
        held_pointer = std::move(p);
    }

    void report() const
    {
        if ( auto sp = held_pointer.lock() )
        {
            std::cout << "Pointer points to " << *sp << "\n";
        }
        else
        {
            std::cout << "Pointer has expired.\n";
        }
    }
};

ВВ этом примере функция observe хранит состояние.

Ее параметр weak_ptr сообщает, что этот переданный указатель не является владельцем, но оставляет за собой возможность владеть позднее, безопасно обнаруживая, истек ли указатель.

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

0 голосов
/ 03 декабря 2018

Слабые указатели полезны для удержания объектов, которые могут быть недоступны позже (без продления срока их службы).Это означает, что они обычно используются для хранения в контейнерах (или переменных).Обычно передают общий указатель, пока объект не будет сохранен, а затем преобразован в слабые указатели.Затем, когда они используются, они должны быть сначала преобразованы в общие указатели, чтобы проверить, все ли они действительны.Таким образом, маловероятно, что вы передадите слабый указатель, кроме как в процессе хранения и поиска, возможно, в вспомогательных функциях.

0 голосов
/ 03 декабря 2018

Если у ваших клиентов есть weak_ptr, и ваша логика может блокировать его или нет, и действует независимо, тогда передайте weak_ptr.

В качестве конкретного тривиального примера:

mutable std::mutex m_mutex;
mutable std::vector<std::weak_ptr<std::function<void(int)>>> m_callbacks;

void clean_callbacks(int x) {
  auto l = std::unique_lock<std::mutex>(m_mutex);
  auto it = std::remove_if( begin(m_callbacks), end(m_callbacks), [](auto w){ return !w.lock(); } );
  m_callbacks.erase( it, end(m_callbacks) );
}
void call_callbacks() {
  clean_callbacks();
  auto tmp = [&]{
    auto l = std::unique_lock<std::mutex>(m_mutex);
    return m_callbacks;
  }();
  for (auto&& wf:tmp) {
    if(auto sf = wf.lock()) {
      (*sf)(x);
    }
  }
}

clean_callbacks имеет лямбду, которая принимает weak_ptr.Он используется для удаления любых m_callbacks, чье время жизни истекло.

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

...