2010-07-09 14 views
7

Mam funkcję, w której chcę wykonać akcję czyszczenia w 90% przypadków, ale w 10% chcę wykonać inną akcję.Czy istnieje sposób zmiany akcji usuwania na istniejącej instancji shared_ptr

Czy istnieje sposób użycia standardowego zakresu kontrolnego, takiego jak shared_ptr<>, aby początkowo mógł mieć jedną akcję usuwania, a później w funkcji, którą można usunąć?

+2

Dlaczego nie wymusić swojej strategii usuwania w swoim niestandardowym deleterze? – Abhay

+0

Po prostu próbowałem uniknąć pisania niestandardowego deletera, kiedy muszę wybrać (obecnie) między 2 funkcjami. –

Odpowiedz

2

Nie sądzę, że można zmienić deleter po utworzeniu shared_ptr.

Ale dlaczego miałbyś to zrobić? Zwykle, gdy tworzysz obiekt, od razu wiesz, jak go zniszczyć. To się nie zmieni.

Jeśli naprawdę musisz wykonać określone zabiegi, nadal możesz podać niestandardowy deleter, który wykonuje specjalne czynności w zależności od wymaganej logiki.

+2

Właśnie wymyśliłem przyczynę, która polega na tym, że można chcieć zastąpić deletera nowym deleterem, który robi to, co robi stary, * i * czymś innym (np. Powiadamia słuchacza o zniszczeniu obiektu). Ale jestem prawie pewny, że nie jest to wykonalne, choćby dlatego, że deleter znajduje się w bloku kontrolnym, więc z pewnością nie można go zastąpić urządzeniem z innym rozmiarem. Tak jak mówisz, potencjał tego zachowania musi znajdować się w "shared_ptr" od samego początku. –

+0

Przypadek użycia, jaki mogę wymyślić, to to, że masz bibliotekę, która zwraca std :: tr1 :: shared_ptr i chcesz przenieść kontrolę do std :: shared_ptr i masz pewność, że std :: shared_ptr przetrwa std :: tr1 :: shared_ptr. Straszne? Absolutnie. –

2

Istnieje ważny powód, aby zmienić deleter. Weźmy na przykład:

int foo(std::shared_ptr<double>& bar) { 
    ... 
    std::shared_ptr<double> p(my_allocator<double>::allocate(), my_deleter<double>()); 
    bar.swap(p); // this copies the deleter 
    ... 
} 

int main(int, char**) { 
    std::shared_ptr<double> d; 
    foo(d); // d now has a new deleter that will be called when it goes out of scope 
    ... 
} 

W tym przypadku funkcja foo() przydziela podwójną * przy użyciu specjalnego przydziału. Musi także zwolnić tę pamięć w specjalny sposób. Dzwoniący nie powinien wiedzieć, jak zwolnić pamięć.

+0

Nic się tutaj nie zmienia. Tworzysz nowe 'std :: shared_ptr', a następnie używasz go jak dowolnego innego obiektu wartości. –

+0

@ kuba-ober: Rozumiem, źle zrozumiałem jego oryginalne pytanie. Masz rację, zdecydowanie chce zmienić deleter dla zarządzanego wskaźnika po jego zbudowaniu, zamiast aktualizować deleter na istniejącym obiekcie shared_ptr (jak mówi tytuł). –

0

To nie ma sensu, ponieważ istnieje jakakolwiek liczba shared_ptr s zarządzania własnością wartości. Musisz zmodyfikować je wszystkie, a to nie jest możliwe. Nie zapominajmy, że blok kontrolny jest szczegółem implementacji, więc "aha, ale zmień go w bloku kontrolnym" nie będzie działać.

Działania usuwania powinny być kontrolowane przez instancję należącą do shared_ptr, np.

class C { 
... 
    void (C::action*)() { &C::action1 }; 
    void action1(); 
    void action2(); 
    ~C() { (this->*action)(); } 
}; 

void test() { 
    std::shared_ptr<C> a; 
    a->action = &C::action2; 
    // action2 gets invoked once `a` falls out of scope 
} 
Powiązane problemy