Các hoạt động di chuyển (như công cụ di chuyển) std::shared_ptrrất rẻ , vì về cơ bản chúng là "đánh cắp con trỏ" (từ nguồn đến đích; chính xác hơn, toàn bộ khối điều khiển trạng thái bị "đánh cắp" từ nguồn đến đích, bao gồm cả thông tin đếm tham chiếu) .
Thay vào đó, sao chép các hoạt động khi std::shared_ptrgọi tăng số tham chiếu nguyên tử (nghĩa là không chỉ ++RefCounttrên một RefCountthành viên dữ liệu số nguyên , mà ví dụ như gọi InterlockedIncrementtrên Windows), tốn kém hơn so với chỉ ăn cắp con trỏ / trạng thái.
Vì vậy, phân tích động lực đếm ref của trường hợp này một cách chi tiết:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
Nếu bạn chuyển sptheo giá trị và sau đó lấy một bản sao bên trong CompilerInstance::setInvocationphương thức, bạn có:
- Khi nhập phương thức,
shared_ptrtham số được sao chép được xây dựng: số lần tăng nguyên tử ref .
- Bên trong cơ thể của phương pháp, bạn sao chép các
shared_ptrtham số vào các thành viên dữ liệu: Ref đếm nguyên tử tăng .
- Khi thoát khỏi phương thức,
shared_ptrtham số bị hủy: ref đếm giảm nguyên tử .
Bạn có hai mức tăng nguyên tử và một lần giảm nguyên tử, với tổng số ba hoạt động nguyên tử .
Thay vào đó, nếu bạn truyền shared_ptrtham số theo giá trị và sau đó std::movebên trong phương thức (như được thực hiện đúng trong mã của Clang), bạn có:
- Khi nhập phương thức,
shared_ptrtham số được sao chép được xây dựng: số lần tăng nguyên tử ref .
- Bên trong cơ thể của phương pháp, bạn
std::movecác shared_ptrtham số vào các thành viên dữ liệu: số lượng ref không không thay đổi! Bạn chỉ đang ăn cắp con trỏ / trạng thái: không có hoạt động đếm số nguyên tử đắt tiền nào được tham gia.
- Khi thoát khỏi phương thức,
shared_ptrtham số bị hủy; nhưng vì bạn đã chuyển sang bước 2, nên không có gì để hủy, vì shared_ptrtham số không còn trỏ đến bất cứ điều gì nữa. Một lần nữa, không có sự suy giảm nguyên tử xảy ra trong trường hợp này.
Điểm mấu chốt: trong trường hợp này bạn chỉ nhận được một lần tăng số nguyên tử, tức là chỉ một thao tác nguyên tử .
Như bạn có thể thấy, điều này tốt hơn nhiều so với hai mức tăng nguyên tử cộng với một lần giảm nguyên tử (cho tổng số ba thao tác nguyên tử) cho trường hợp sao chép.