2012-11-07 16 views
10

Ich brauche oft so etwas wie dies mehr als tun:Wie die Verwendung von std :: bind mit std kombinieren :: shared_ptr

AsyncOperation * pAsyncOperation = new AsyncOperation(); 
auto bindOperation = std::bind(&AsyncOperation::operator(), std::ref(*pAsyncOperation)); 
std::thread thread(bindOperation); 
thread.join(); 

mit AsyncOperation jede benutzerdefinierte Klasse sein operator()(auch bekannt als Funktors Umsetzung oder Funktionsobjekt).

Ist es möglich, der std::bind eine std::shared_ptr anstelle einer std::ref zu verwenden? Dies würde Speicherverluste verhindern, ohne dass ich eine Referenz auf pAsyncOperation behalten müsste, und würde die AsyncOperation automatisch am Ende des Threads löschen, das ist das Ende dieser asynchronen Aufgabe.

EDIT: Ich habe nicht immer Zugriff auf std :: thread, die Thread-Bibliothek kann boost :: thread oder sogar andere plattformabhängige Threads sein. Und folglich keinen Zugriff auf std :: async.

Mein Hauptproblem ist eine Vorstellung von Besitz in der std :: bind.

+0

Haben Sie versucht, 'std :: shared_ptr' zu benutzen? Sieht so aus, als kompiliere es ohne Probleme: http://liveworkspace.org/code/1e83d9698703711b7ed2ce0d44cf86f2 – PiotrNycz

+1

Was Sie wissen müssen, ist, dass 'std :: bind 'gebundene Argumente nach Wert speichert (dh wie übergeben), wenn Sie also ein owning übergeben Zeiger nach Wert als einer der Parameter, dieser Zeiger wird in den resultierenden Funktor "kopiert" und hält somit Besitz, selbst nachdem der ursprüngliche 'shared_ptr' den Gültigkeitsbereich verlassen hat. – haelix

Antwort

10

Dies funktioniert:

struct AsyncOperation { 
    void operator()() 
    { 
     std::cout << "AsyncOperation" << '\n'; 
    } 
}; 

int main() { 
    std::shared_ptr<AsyncOperation> pAsyncOperation = std::make_shared<AsyncOperation>(); 
    auto bindOperation = std::bind(&AsyncOperation::operator(), pAsyncOperation); 
    std::thread thread(bindOperation); 
    thread.join(); 
} 

See: http://liveworkspace.org/code/4bc81bb6c31ba7b2bdeb79ea0e02bb89

+0

Müssen Sie 'make_shared' verwenden oder wird' std :: shared_ptr pAsyncOperation (new AsyncOperation()); – akaltar

+1

@akaltar können Sie beide "Stile" verwenden - aber make_shared ist besser - lesen Sie: https://StackOverflow.com/questions/31232146/why-is-it-besser-zu-use-stdmake-inste-of-the- Konstrukteur – PiotrNycz

7

Benötigen Sie AsyncOperation, um dynamisch zugewiesen zu werden? Wenn nicht, würde ich das tun:

auto f = std::async([]{ AsyncOperation()(); }); 
f.wait(); 

sonst:

std::unique_ptr<AsyncOperation> op(new AsyncOperation); 
auto f = std::async([&]{ (*op)(); }); 
f.wait(); 

Sie natürlich std::thread verwenden können, aber es kann mehr Probleme (das heißt die Ausnahmebehandlung in anderen Thread) bereitzustellen. std::bind hat auch seine eigenen Probleme und Sie werden wahrscheinlich besser mit einem Lambda enden.

Wenn Sie wirklich ein Eigentum an anderem Thread müssen passieren können Sie auch das tun:

std::unique_ptr<AsyncOperation> op(new AsyncOperation); 
auto f = std::async([&](std::unique_ptr<AsyncOperation> op){ (*op)(); }, std::move(op)); 
f.wait(); 

als Lambda noch nicht bewegen Typen unterstützen einfängt.

Ich hoffe, dass hilft.

Verwandte Themen