Если бы я мог удалить все исходные указатели *
из моего кода, потому что использование их может быть небезопасным потоком, а намерения дизайна не ясны (необязательное значение, право собственности и т.д.).
Иногда, однако, не так просто не использовать указатели. Например, мы склонны использовать указатели для базового типа в контейнере полиморфных типов:
class A : noncopyable { ... };
class B : public A { ... };
std::vector<A*> v;
v.emplace_back(new B);
// temporary container for some operation
std::vector<A*> selected;
if(check())
selected.emplace_back(v.front());
Что вы можете сказать о коде выше? Кто является владельцем? Это общая собственность или нет? Именно поэтому мы должны сделать это для v
:
std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());
Теперь ясно, что v
владеет объектами, но мне все еще не нравится, что selected
имеет необработанный указатель и делает мой дизайн неинтуитивным. В стандартной библиотеке С++ я считаю, что есть только один тип, который мог бы выполнить эту работу - std:: reference_wrapper:
std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());
// temporary container for some operation
std::vector<std::reference_wrapper<A>> selected;
if(check())
selected.emplace_back(*v.front());
Как вы относитесь к этому коду? Это хорошая практика? Я знаю, что std::ref()
и std::cref
, где предназначено, в первую очередь, работать с шаблонами, но кажется, что здесь мы также можем использовать его, чтобы четко сформулировать наше намерение дизайна. Единственная проблема, которую я вижу, заключается в том, что мне нужно разыгрывать std::reference_wrapper
с помощью get()
, а внутри operator*()
или operator->()
нет такого интерфейса, как в контейнере с unique_ptr
. Должен ли я писать что-то подобное самостоятельно? Или, возможно, reference_wrapper может быть расширен для такого варианта использования в будущих версиях С++? Пожалуйста, поделитесь своими отзывами.
EDIT: я изменил образцы кода, чтобы лучше показать намерение.