2017-08-29 17 views
7

Tôi có C++ sau (11) Mã:Tại sao không std :: di chuyển trên một std :: unique_lock có bất kỳ tác dụng?

#include <mutex> 

void unlock(std::unique_lock<std::mutex> && ulock) 
{ 
} 

int main(void) 
{ 
    std::mutex m; 
    std::unique_lock<std::mutex> ulock(m); 

    unlock(std::move(ulock)); 

    if (ulock.mutex() == &m || ulock.owns_lock()) 
    { 
     throw std::runtime_error(""); 
    } 

    return 0; 
} 

Những gì tôi không thể tìm ra được lý do tại sao các mutex vẫn tổ chức sau khi trở về từ unlock(). Kỳ vọng của tôi là std::move() làm cho khóa bị lệch khỏi phạm vi (và được mở khóa bởi trình phá hủy) khi trở về từ cuộc gọi đến unlock(). Ít nhất, có vẻ như số std::move() sẽ khiến ulock trở thành "không bị ràng buộc" từ mutex m.

Tôi đang thiếu gì?

+7

'std :: move' không tự di chuyển bất cứ thứ gì. Nó chỉ đơn giản là đưa một giá trị vào một tham chiếu rvalue, cho phép nó là một đối số của các hàm tạo di chuyển và như vậy. Những người lần lượt có thể ăn cắp các nội bộ của (những gì họ nghĩ là) tạm thời. Nhưng mã của bạn không gọi bất kỳ mã nào trong số đó. 'mở khóa (std :: move (ulock));' là một công cụ không phức tạp. –

+0

Xác định 'mở khóa' để lấy' std :: unique_lock' theo giá trị, sau đó di chuyển vào nó, để xem các hiệu ứng – WhiZTiM

+3

Tôi đã giả định rằng std :: move() đã gọi hàm khởi tạo di chuyển cho unique_lock. Có vẻ như đó không phải là trường hợp ... Thay vào đó, tham chiếu rvalue trong 'mở khóa()' là một "thông báo" của các loại * nó * có thể sử dụng constructor di chuyển nên chọn (nếu điều đó có ý nghĩa). –

Trả lời

12
void unlock(std::unique_lock<std::mutex> && ulock) 

đây ulock là một tài liệu tham khảo . Một loại tham chiếu đặc biệt, nhưng vẫn là một tham chiếu. Nó chỉ là một bí danh cho một đối tượng khác. Sự sáng tạo của nó không liên quan đến việc tạo ra một vật thể mới, hay bất kỳ sự chuyển giao quyền sở hữu nào. Tương tự như vậy, kết thúc vòng đời của nó không dẫn đến bất kỳ cuộc gọi destructor nào, nó chỉ có nghĩa là bạn đã mất bí danh để đề cập đến một số đối tượng khác (không phải là nó quan trọng, vì hàm này vẫn kết thúc).

Nếu bạn muốn chuyển quyền sở hữu, bạn cần một đối tượng, vì vậy đi qua giá trị thay vì bằng cách tham khảo:

void unlock(std::unique_lock<std::mutex> ulock) 

Bây giờ, bạn sẽ phải move khóa gốc, vì std::unique_lock không hỗ trợ sao chép xây dựng, chỉ di chuyển xây dựng.

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