2015-06-23 25 views
5

Có một điều về std::thread mà tôi không hiểu: lý do tại sao hàm tạo của std::thread có chức năng để chạy theo rvalue?Tại sao std :: thread có chức năng chạy theo rvalue?

Tôi thường muốn chạy một Functor với một số thành viên khác. Như thế này:

struct Function 
{ 
    void operator() (/* some args */) 
    { 
     /* some code */ 
    } 

    /* some members */ 
} 


void run_thread() 
{ 
    Functor f(/* some data */); 
    std::thread thread(f, /* some data */); 

    /* do something and wait for thread to finish */ 
} 

Với thực hiện hiện tại std::thread Tôi phải chắc chắn đối tượng của tôi đang triển khai ngữ nghĩa di chuyển. Tôi không hiểu tại sao tôi không thể vượt qua nó bằng cách tham chiếu.

Câu hỏi bổ sung là: có nghĩa là gì khi tham khảo hàm theo giá trị rvalue? Lambda biểu hiện?

+4

'std :: constructor của thread' có chức năng của nó bằng cách chuyển tiếp tham chiếu. –

+0

Đối tượng của bạn không cần triển khai ngữ nghĩa di chuyển. Nếu di chuyển không được hỗ trợ, nó chỉ là khu nghỉ mát để sao chép. – nwp

+0

@nwp: những gì trong trường hợp, khi đối tượng đã xóa bản sao xây dựng? Tại sao bản sao là cần thiết? –

Trả lời

6

Trong phương thức run_thread của bạn f là một biến tự động. Điều đó có nghĩa là ở dưới cùng của phạm vi f sẽ bị hủy. Bạn tuyên bố rằng bạn sẽ "chờ đợi cho thread để kết thúc" nhưng trình biên dịch/hệ thống thời gian chạy không biết điều đó! Nó phải giả định rằng f sẽ bị xóa, có thể trước khi luồng được cho là gọi phương thức của nó có cơ hội bắt đầu.

Bằng cách sao chép (hoặc di chuyển) f, hệ thống thời gian chạy sẽ kiểm soát toàn bộ thời gian của bản sao f và có thể tránh một số sự cố khó xử, khó gỡ lỗi.

3

std::reference_wrapper sẽ hiển thị operator() cho đối tượng được bao bọc. Nếu bạn sẵn sàng thực hiện bảo trì suốt đời thủ công, std::thread t(std::ref(f)); sẽ chạy f bằng cách tham chiếu.

Tất nhiên trong mã của bạn, điều này gây ra hành vi không xác định vì bạn không quản lý thời gian sống đúng cách.


Cuối cùng, lưu ý rằng thread là công cụ "mã khách hàng" kém. async là một liên lạc tốt hơn, nhưng thực sự bạn muốn có một hàng đợi công việc với các biến số packaged_task s và future s và điều kiện. C++ 11 bổ sung hỗ trợ luồng đủ để viết một hệ thống luồng khá, nhưng nó cung cấp các công cụ nguyên gốc, không tốt "mã khách hàng".

Trong chương trình đồ chơi, điều đó có thể là đủ.

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