2012-11-07 22 views
10

ho bisogno di fare qualcosa di simile più spesso:Come combinare l'uso di std :: bind con std :: shared_ptr

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

con AsyncOperation essere qualsiasi classe personalizzata attuazione operator()(noto anche come functor o oggetto funzionale).

È possibile indicare a std::bind l'utilizzo di std::shared_ptr anziché std::ref? Ciò eviterebbe perdite di memoria, senza la necessità di mantenere un riferimento su pAsyncOperation e si eliminerebbe automaticamente il AsyncOperation alla fine del thread, ovvero la fine di questa attività asincrona.

MODIFICA: Non sempre ho accesso a std :: thread, la libreria di thread può essere boost :: thread o anche qualsiasi altro thread dipendente dalla piattaforma. E di conseguenza, non accedere a std :: async.

Il mio problema principale è avere una nozione di possesso in std :: bind.

+0

Hai provato ad usare 'std :: shared_ptr'? Sembra che compili senza problemi: http://liveworkspace.org/code/1e83d9698703711b7ed2ce0d44cf86f2 – PiotrNycz

+1

Quello che devi sapere è che 'std :: bind' memorizza gli argomenti associati per valore (cioè, come passato), quindi, se passi un possesso puntatore per valore come uno dei parametri, quel puntatore viene "copiato" nel functor risultante, quindi, mantenendo la proprietà anche dopo che l'originale 'shared_ptr' esce dall'ambito. – haelix

risposta

10

Questo funziona:

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

È necessario utilizzare 'make_shared', oppure' std :: shared_ptr pAsyncOperation (new AsyncOperation()); 'do? – akaltar

+1

@akaltar puoi usare entrambi gli "stili" - ma make_shared è meglio - leggi: https://stackoverflow.com/questions/31232146/why-is-it-better-to-use-stdmake-instead-of-the- costruttore – PiotrNycz

7

È necessario assegnare lo standard AsyncOperation in modo dinamico? In caso contrario, avrei dovuto farlo:

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

altrimenti:

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

Ovviamente si può utilizzare std::thread, ma può fornire più problemi (cioè di gestione delle eccezioni in altro thread). std::bind ha anche i suoi problemi e probabilmente starai meglio con un lambda.

Se avete veramente bisogno di passare una proprietà per altro thread si può anche fare che:

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

come lambda non supportano mossa di tipo cattura ancora.

Spero che questo aiuti.

Problemi correlati