Gdybym mógł, usunąłbym wszystkie surowe wskaźniki *
z mojego kodu, ponieważ ich używanie może nie być bezpieczne dla wątków, a intencje projektu nie są jasne (wartość opcjonalna, własność, itp.) . Czasami jednak nie jest łatwo nie używać wskaźników. Na przykład mamy tendencję do używania wskaźników dla typu podstawowego w kontenerze typów polimorficznych:std :: reference_wrapper <T> użycie w kontenerze
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());
Co możesz powiedzieć o powyższym kodzie? Kto jest właścicielem? Czy jest to własność współdzielona, czy nie? To dlaczego my prawdopodobnie zrobić dla v
:
std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());
Teraz jest jasne, że v
jest właścicielem obiektów, ale nadal nie tak selected
ma wskaźnik surowego i sprawia, że mój projekt nie intuicyjne. Patrząc w bibliotece standard C++ myślę, że istnieje tylko jeden typ, który mógłby wykonać zadanie - 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());
Jak się czujesz o tym kodem? Czy to dobra praktyka? Wiem, że std::ref()
i std::cref
, gdzie ma przede wszystkim pracować z szablonami, ale wydaje się, że tutaj możemy również użyć go do wyraźnego określenia naszego zamiaru projektowego. Jedyny problem, jaki widzę, to to, że muszę usunąć dereferencję std::reference_wrapper
z get()
i nie ma w środku operator*()
ani operator->()
, aby mieć taki sam interfejs jak w kontenerze z unique_ptr
. Czy powinienem napisać coś podobnego na własną rękę? A może referencyjny_wrapper mógłby zostać rozszerzony na taki przypadek użycia w przyszłych wersjach C++? Podziel się swoją opinią.
EDYCJA: Zmieniłem próbki kodu, aby lepiej pokazać zamiar.
Jaki jest czas życia "wybranego"? Czy jest zagwarantowane, że zostanie zniszczony (lub opróżniony) przed obiektami, na które punkt jego elementów zostanie zniszczony? Jeśli tak, to użyj surowych wskaźników: nie ma potrzeby współdzielenia własności. Nie ma nic złego w używaniu surowych wskaźników w C++; po prostu upewnij się, że surowe wskazówki nie wskazują na obiekt wskazany. –
Wygląda na to, że są one 'shared_ptr''s. – perreal
@JamesMcNellis Masz rację. Wydaje mi się, że z takiego małego urywka jest jasne, do czego służą "wybrane" i "v". Jednak w większym zakresie/klasie nie jest łatwo dostrzec związki w projekcie. W niektórych metodach zaczynasz pracę nad 'selected' tylko bez widoku na' v' i zaczynasz się zastanawiać, co oznacza ten wskaźnik. Czy jest to wartość opcjonalna, własność lub po prostu wskaźnik klasy bazowej? Szukam ładnego sposobu na przedstawienie mojej intencji projektu bez kosztów ogólnych w czasie wykonywania. –