Использование необработанного владения указателем является плохой практикой.
Использование необработанного указателя наблюдателя - это нормально ... но поскольку существующий код может использовать необработанные указатели-владельцы, необработанный указатель является неоднозначным между указателем наблюдателя ивладеющий указатель.
Такие типы, как std::experimental::observer_ptr<T>
, были введены для ясного выражения намерений.(но это в основном просто указатель).
Указатели-наблюдатели не владеют данными, поэтому время жизни данных должно быть длиннее, чем указатель-наблюдателя.
В вашем случае возможны следующие варианты:
class Manager
{
public:
std::vector</*const*/ T*> filter_view_1(/**/) /*const*/;
std::vector<std::experimental::observer_view</*const*/T>> filter_view_2(/**/) /*const*/;
std::vector<std::reference_wrapper</*const*/T>> filter_view_3(/**/) /*const*/;
private:
std::vector<std::unique_ptr<T>> data;
};
Таким образом, возвращаемые значения должны использоваться до того, как Manager::data
будет «очищен».
Или, чтобы гарантировать срок службы:
class Manager
{
public:
std::vector<std::shared_ptr</*const*/T>> filter_view_4(/**/) /*const*/;
std::vector<std::weak_ptr</*const*/T>> filter_view_5(/**/) /*const*/;
private:
std::vector<std::shared_ptr<T>> data;
};
filter_view_4
продлитьвремя жизни, тогда как filter_view_5
позволяет проверять время жизни объекта.
Существуют также различные подходы для недопущения внутреннего, такие как:
class Manager
{
public:
// std::function might be replaced by template for the Functor
void for_each_filtered(std::function<bool(const T&)> filter,
std::function<void(/*const*/ T&)> action) /*const*/
{
for (auto& d : data) {
if (filter(*d)) {
action(*d)
}
}
}
private:
std::vector<std::unique_ptr<T>> data;
};