2012-11-07 37 views
10

tôi cần phải làm một cái gì đó như thế này hơn thường:Làm thế nào để kết hợp việc sử dụng std :: ràng buộc với std :: shared_ptr

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

với AsyncOperation là bất kỳ lớp tùy chỉnh thực hiện operator()(còn gọi là functor hoặc đối tượng hàm).

Có thể chỉ định cho std::bind để sử dụng số std::shared_ptr thay vì std::ref? Điều này sẽ ngăn chặn rò rỉ bộ nhớ, mà không cần phải giữ tham chiếu trên pAsyncOperation và tự động xóa AsyncOperation ở cuối chuỗi, đó là kết thúc của tác vụ không đồng bộ này.

EDIT: Tôi không phải lúc nào cũng có quyền truy cập vào std :: thread, thư viện chủ đề có thể được tăng :: thread hoặc thậm chí bất kỳ chủ đề phụ thuộc nền tảng nào khác. Và do hậu quả, không truy cập vào std :: async.

Vấn đề chính của tôi là có khái niệm sở hữu trong tiêu chuẩn std :: bind.

+0

Bạn đã cố gắng sử dụng 'std :: shared_ptr'? Có vẻ như biên dịch không có vấn đề: http://liveworkspace.org/code/1e83d9698703711b7ed2ce0d44cf86f2 – PiotrNycz

+1

Những gì bạn cần biết là 'std :: bind' lưu trữ các đối số liên kết theo giá trị (tức là, khi được thông qua), do đó, nếu bạn chuyển quyền sở hữu con trỏ bởi giá trị là một trong các tham số, con trỏ đó được 'sao chép' vào functor kết quả, do đó, giữ quyền sở hữu ngay cả sau khi 'shared_ptr' ban đầu đi ra khỏi phạm vi. – haelix

Trả lời

10

này hoạt động:

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(); 
} 

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

+0

Bạn có cần sử dụng 'make_shared', hoặc sẽ' std :: shared_ptr pAsyncOperation (new AsyncOperation()); 'do? – akaltar

+1

@akaltar bạn có thể sử dụng cả hai kiểu "" - nhưng make_shared là tốt hơn - đọc: https://stackoverflow.com/questions/31232146/why-is-it-better-to-use-stdmake-instead-of-the- constructor – PiotrNycz

7

Bạn có cần AsyncOperation để được phân bổ động không? Nếu không, tôi sẽ làm điều đó:

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

khác:

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

Bạn có thể sử dụng tất nhiên std::thread, nhưng nó có thể cung cấp thêm các vấn đề (ví dụ: xử lý ngoại lệ trong chủ đề khác). std::bind cũng có những vấn đề riêng của nó và bạn có thể sẽ kết thúc tốt hơn với một lambda.

Nếu bạn thực sự cần phải vượt qua một quyền sở hữu cho chủ đề khác mà bạn cũng có thể làm điều đó:

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

như lambdas không hỗ trợ loại di chuyển chụp được nêu ra.

Tôi hy vọng điều đó sẽ hữu ích.

Các vấn đề liên quan