C ++ 11 unique_ptr và shared_ptr có thể chuyển đổi sang kiểu của nhau không?


99

Thư viện chuẩn C ++ 11 có cung cấp bất kỳ tiện ích nào để chuyển đổi từ a std::shared_ptrsang std::unique_ptr, hoặc ngược lại không? Hoạt động này có an toàn không?


Vui lòng xác định "hoạt động an toàn". Bạn đang tìm kiếm loại an toàn nào? quản lý an toàn trọn đời? Chủ đề an toàn?
jaggedSpire

2
"STL" không có nghĩa là thư viện tiêu chuẩn. STL không liên quan gì shared_ptr.
tò mò

1
@jaggedSpire an toàn Chủ đề có nghĩa là bạn có chủ sở hữu sử dụng trong chủ đề khác nhau, tức là số lượng sử dụng không phải là 1.
curiousguy

@curiousguy Tôi biết điều đó. Quan điểm của tôi là "an toàn" không được xác định rõ trong câu hỏi của OP, và anh ấy cần phải làm rõ loại "an toàn" mà anh ấy muốn nói vì có nhiều loại.
jaggedSpire

Câu trả lời:


161

std::unique_ptr là cách C ++ 11 để thể hiện quyền sở hữu độc quyền, nhưng một trong những tính năng hấp dẫn nhất của nó là nó dễ dàng và hiệu quả chuyển đổi thành std::shared_ptr .

Đây là một phần quan trọng giải thích tại sao lại std::unique_ptrrất phù hợp với vai trò là kiểu trả về hàm gốc. Các hàm nhà máy không thể biết liệu người gọi có muốn sử dụng ngữ nghĩa quyền sở hữu độc quyền cho đối tượng mà họ trả lại hay không hay quyền sở hữu chung (tức là std::shared_ptr) sẽ phù hợp hơn. Bằng cách trả về a std::unique_ptr, các nhà máy cung cấp cho người gọi một con trỏ thông minh hiệu quả nhất, nhưng chúng không cản trở người gọi thay thế nó bằng con trỏ linh hoạt hơn của nó.

std::shared_ptrđể std::unique_ptrkhông được phép. Khi bạn đã chuyển quản lý suốt đời của một tài nguyên sang một std::shared_ptr, bạn sẽ không thay đổi suy nghĩ. Ngay cả khi số lượng tham chiếu là một, bạn không thể đòi lại quyền sở hữu tài nguyên để cóstd::unique_ptr quản lý nó.

Tham khảo: C ++ hiện đại hiệu quả. 42 CÁCH CỤ THỂ ĐỂ NÂNG CAO VIỆC SỬ DỤNG C ++ 11 VÀ C ++ 14 của bạn. Scott Meyers.

Trong ngắn hạn, bạn có thể dễ dàng và hiệu quả chuyển đổi a std::unique_ptrthành std::shared_ptrnhưng bạn không thể chuyển đổi std::shared_ptrsang std::unique_ptr.

Ví dụ:

std::unique_ptr<std::string> unique = std::make_unique<std::string>("test");
std::shared_ptr<std::string> shared = std::move(unique);

hoặc là:

std::shared_ptr<std::string> shared = std::make_unique<std::string>("test");

9
...Bạn làm nó như thế nào?
Jake

4
@Jake Tôi đã thêm một ví dụ
chema989

Cần biết rằng mặc dù không được phép, trình biên dịch (ít nhất là không phải gcc) sẽ thực sự không ngăn chặn (hoặc thậm chí cảnh báo) nếu bạn vô tình (ví dụ bằng cách thay đổi kiểu con trỏ của một biến thành viên) gán a std::unique_ptrcho a std::shared_ptr.
StefanQ

-8

Đã đưa ra unique_ptr u_ptr, hãy tạo shared_ptr s_ptr:

std::shared_ptr<whatever> s_ptr(u_ptr.release());

Đi theo con đường khác là không thực tế.


29
Đây là cách "đúng":std::shared_ptr<whatever> s_ptr(std::move(u_ptr));
emlai

6
Và đây là pedantic "đúng" cách:std::shared_ptr<whatever> s_ptr{std::move(u_ptr)};
polyvertex

3
Điều gì kém an toàn hơn về nó?
nmr

7
@VioletGiraffe • Tôi cho rằng polyvertex đang ủng hộ việc sử dụng cú pháp danh sách khởi tạo mới - giúp tránh các chuyển đổi thu hẹp im lặng và hỗ trợ khởi tạo thành viên với một cú pháp thống nhất - như một thói quen tốt để thực hiện. Sáu của một, nửa tá của cái còn lại?
Eljay

8
@nmr Đó là không an toàn vì bạn có thể mất Deleterđược lưu trữ bên trongunique_ptr
Zang Mingjie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.