2010-07-09 4 views
7

Ich habe eine Funktion, wo ich eine Bereinigung Aktion in 90% der Zeit durchgeführt werden soll, aber in 10% möchte ich eine andere Aktion durchgeführt werden.Gibt es eine Möglichkeit zum Ändern der Löschaktion für eine vorhandene Instanz von shared_ptr

Gibt es eine Möglichkeit, ein Standard-Scoped-Steuerelement wiezu verwenden, so dass es zunächst eine Löschaktion haben kann und später in der Funktion die Löschaktion geändert werden kann?

shared_ptr<T> ptr(new T, std::mem_fun_ref(&T::deleteMe)); 
ptr.pn.d = std::mem_fun_ref(&T::queueMe); 
+2

Warum erzwingen Sie nicht Ihre Löschstrategien in Ihrem benutzerdefinierten Löscher selbst? – Abhay

+0

Ich habe gerade versucht zu vermeiden, den benutzerdefinierten Deleter zu schreiben, wenn ich nur (gerade) zwischen 2 Mitgliedsfunktionen wählen muss. –

Antwort

2

Ich glaube nicht, dass Sie die deleter ändern können, sobald die shared_ptr erstellt wurde.

Aber warum würden Sie das tun? Normalerweise wissen Sie beim Erstellen eines Objekts sofort, wie es zerstört werden muss. Dies wird sich wahrscheinlich nicht ändern.

Wenn Sie wirklich bestimmte Behandlungen ausführen müssen, können Sie immer noch einen benutzerdefinierten Löschdienst bereitstellen, der abhängig von der erforderlichen Logik besondere Dinge erledigt.

+2

Ich habe gerade einen Grund gedacht, was ist, dass Sie möglicherweise den Deleter durch einen neuen Deleter ersetzen könnten, der das tut, was der alte tut, * und * etwas anderes (wie einen Listener über die Objektzerstörung benachrichtigen). Aber ich bin mir ziemlich sicher, dass es nicht durchführbar ist, und sei es nur, weil der Deleter im Kontrollblock ist, also könnte man ihn sicherlich nicht durch einen Deleter mit einer anderen Größe ersetzen. Wie du sagst, muss das Potenzial für dieses Verhalten von Anfang an im "shared_ptr" sein. –

+0

Der Anwendungsfall, den ich mir vorstellen kann, ist, dass Sie eine Bibliothek haben, die ein std :: tr1 :: shared_ptr zurückgibt, und Sie die Kontrolle auf ein std :: shared_ptr verschieben möchten und Sie sind zuversichtlich, dass die std :: shared_ptr die std :: tr1 :: shared_ptr. Schrecklich? Absolut. –

2

Es gibt einen guten Grund, den Deleter zu ändern. Nehmen Sie dies zum Beispiel:

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 
    ... 
} 

In diesem Fall wird die foo() Funktion ordnet eine doppelte * einige spezielle allocator verwenden. Es muss diese Erinnerung auch auf besondere Weise befreien. Der Anrufer sollte nicht wissen müssen, wie er den Speicher freigibt.

+0

Nichts wird hier verändert. Sie erstellen ein neues 'std :: shared_ptr' und verwenden es dann wie jedes andere Wertobjekt. –

+0

@ kuba-ober: Ich verstehe, ich habe seine ursprüngliche Frage missverstanden. Du hast Recht, er möchte definitiv den Deleter für den verwalteten Zeiger ändern, nachdem er erstellt wurde, anstatt den Deleter auf einem vorhandenen shared_ptr-Objekt zu aktualisieren (wie der Titel sagt). –

0

Dies macht keinen Sinn, da es eine Anzahl von shared_ptr s gibt, die den Besitz des Wertes verwalten. Sie müssten sie alle modifizieren, und das ist nicht machbar. Vergessen wir nicht, dass ein Kontrollblock ein Implementierungsdetail ist, also wird "aha, aber ändere es im Kontrollblock" nicht funktionieren.

Die Löschaktionen sollten von der Instanz gesteuert werden, deren Eigentümer shared_ptr ist, z.

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 
} 
Verwandte Themen