Tôi nghe nói auto_ptr
là không được chấp nhận trong C ++ 11. Lý do cho điều này là gì?
Ngoài ra, tôi muốn biết sự khác biệt giữa auto_ptr
và shared_ptr
.
Câu trả lời:
Sự thay thế trực tiếp cho auto_ptr
(hoặc điều gần nhất với một) là unique_ptr
. Về "vấn đề", nó khá đơn giản: auto_ptr
chuyển quyền sở hữu khi nó được chỉ định. unique_ptr
cũng chuyển quyền sở hữu, nhưng nhờ mã hóa ngữ nghĩa chuyển động và sự kỳ diệu của các tham chiếu rvalue, nó có thể làm như vậy một cách tự nhiên hơn đáng kể. Nó cũng "phù hợp" với phần còn lại của thư viện tiêu chuẩn tốt hơn đáng kể (mặc dù, công bằng mà nói, một số điều đó là nhờ phần còn lại của thư viện thay đổi để phù hợp với ngữ nghĩa chuyển động thay vì luôn yêu cầu sao chép).
Việc thay đổi tên cũng là (IMO) một điều đáng hoan nghênh - auto_ptr
không thực sự cho bạn biết nhiều về những gì nó cố gắng tự động hóa, trong khi đó unique_ptr
là một mô tả khá hợp lý (nếu ngắn gọn) về những gì được cung cấp.
auto_ptr
tên: tự động đề xuất tự động như trong biến tự động và nó đề cập đến một điều phải auto_ptr
làm: phá hủy tài nguyên được quản lý trong trình hủy của nó (khi nó vượt ra khỏi phạm vi).
auto_ptr
: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…
std::sort
không có chuyên môn cho unique_ptr
. Thay vào đó, nó đã được chỉ định lại để không bao giờ sao chép. Vì vậy, auto_ptr
thực sự làm việc với hiện đại sort
. Nhưng C ++ 98/03 sort
chỉ là một thuật toán ví dụ ở đây: Bất kỳ thuật toán chung nào (do std cung cấp hoặc do người dùng viết) giả định rằng cú pháp sao chép có ngữ nghĩa sao chép sẽ có thể có lỗi thời gian chạy nếu được sử dụng với auto_ptr
, vì chuyển độngauto_ptr
âm thầm với cú pháp sao chép . Vấn đề là nhiều lớn hơn chỉ . sort
Tôi thấy các câu trả lời hiện có rất tuyệt, nhưng từ PoV của các con trỏ. IMO, một câu trả lời lý tưởng nên có câu trả lời theo quan điểm của người dùng / lập trình viên.
Điều đầu tiên trước tiên (như Jerry Coffin đã chỉ ra trong câu trả lời của anh ấy)
shared_ptr: Nếu bạn lo lắng về việc giải phóng tài nguyên / bộ nhớ VÀ nếu bạn có nhiều hơn một hàm có thể đang sử dụng đối tượng AT-DIFFERENT lần, thì hãy chọn shared_ptr.
Theo DIFFERENT-Times, hãy nghĩ đến một tình huống trong đó đối tượng-ptr được lưu trữ trong nhiều cấu trúc dữ liệu và sau đó được truy cập. Nhiều chủ đề, tất nhiên là một ví dụ khác.
unique_ptr: Nếu tất cả những gì bạn quan tâm là giải phóng bộ nhớ và quyền truy cập vào đối tượng là SEQUENTIAL, thì hãy chuyển sang unique_ptr.
Ý tôi là SEQUENTIAL, tại bất kỳ thời điểm nào đối tượng sẽ được truy cập từ một ngữ cảnh. Ví dụ: một đối tượng đã được tạo và được sử dụng ngay sau khi được tạo bởi người tạo. Sau khi tạo, đối tượng được lưu trữ trong cấu trúc dữ liệu FIRST . Sau đó, đối tượng bị hủy sau cấu trúc dữ liệu ONE hoặc được chuyển đến cấu trúc dữ liệu SECOND .
Từ dòng này, tôi sẽ coi _ptr được chia sẻ / duy nhất là con trỏ thông minh. (auto_ptr cũng là một con trỏ thông minh NHƯNG vì những sai sót trong thiết kế của nó, chúng đang không được dùng nữa và điều mà tôi nghĩ rằng tôi sẽ chỉ ra trong các dòng tiếp theo, chúng không nên được nhóm với con trỏ thông minh.)
Một lý do quan trọng nhất giải thích tại sao auto_ptr không được dùng nữa để thay thế cho con trỏ thông minh là ngữ nghĩa gán Nếu không phải vì lý do đó, họ sẽ thêm tất cả các tính năng mới của ngữ nghĩa chuyển vào auto_ptr thay vì phản đối nó. Vì ngữ nghĩa gán là tính năng không thích nhất, họ muốn tính năng đó biến mất, nhưng vì có mã được viết sử dụng ngữ nghĩa đó, (mà ủy ban tiêu chuẩn không thể thay đổi), họ phải bỏ auto_ptr, thay vì sửa đổi nó.
Từ liên kết: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
Loại bài tập được unqiue_ptr hỗ trợ
Từ: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
Loại bài tập được auto_ptr hỗ trợ
Bây giờ đi đến lý do TẠI SAO bản thân bài tập sao chép lại bị không thích, tôi có lý thuyết này:
Hành vi ngoài ý muốn thực sự không thích và do đó không thích auto_ptr.
(Đối với 3,1415926536% lập trình viên cố tình muốn chuyển quyền sở hữu C ++ 11 đã cho họ std :: move (), điều này làm cho ý định của họ trở nên rõ ràng đối với tất cả những người thực tập sẽ đọc và duy trì mã.)
auto_ptr
giá trị trỏ đến cùng một đối tượng (vì chúng không trao quyền sở hữu chung, cái đầu tiên chết sẽ để lại cho cái kia một di sản gây chết người; điều này cũng đúng với unique_ptr
cách sử dụng), bạn có thể đề xuất những gì dự định trong những người còn lại 96,8584073465% của tất cả mức sử dụng?
*a=*b;
Ở đây chỉ có giá trị của b được sao chép vào a. Tôi hy vọng Quyền sở hữu của cả a và b vẫn thuộc về cùng một người. Bạn đã đề cập như khoản nợ sẽ được chuyển. Nó sẽ như thế nào?
auto_ptr
đối tượng. Việc gán cho / từ giá trị trỏ đến của nó không ảnh hưởng đến, cũng không liên quan đến quyền sở hữu. Tôi hy vọng bạn vẫn không sử dụng auto_ptr
?
Tuy nhiên, một người khác tiếp tục giải thích sự khác biệt ....
Về mặt chức năng, C ++ 11 std::unique_ptr
là "cố định" std::auto_ptr
: cả hai đều phù hợp khi - tại bất kỳ thời điểm nào trong quá trình thực thi - phải có một chủ sở hữu con trỏ thông minh duy nhất cho một đối tượng trỏ đến.
Sự khác biệt quan trọng là trong xây dựng bản sao hoặc chuyển nhượng từ một con trỏ thông minh chưa hết hạn khác, được hiển thị trên các =>
dòng bên dưới:
std::auto_ptr<T> ap(...);
std::auto_ptr<T> ap2(get_ap_to_T()); // take expiring ownership
=> std::auto_ptr<T> ap3(ap); // take un-expiring ownership ala ap3(ap.release());
ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL
std::unique_ptr<T> up(...);
std::unique_ptr<T> up2(get_up_to_T()); // take expiring ownership
=> std::unique_ptr<T> up3(up); // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up)); // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release()); // EXPLICIT code allowed
Ở trên, ap3
lặng lẽ "đánh cắp" quyền sở hữu *ap
, để ap
đặt thành a nullptr
, và vấn đề là điều đó có thể xảy ra quá dễ dàng, mà lập trình viên không nghĩ đến sự an toàn của nó.
Ví dụ: nếu a class
/ struct
có một std::auto_ptr
thành viên, thì việc tạo một bản sao của một thể hiện sẽ release
khiến con trỏ từ thể hiện đó được sao chép: đó là ngữ nghĩa kỳ lạ và khó hiểu một cách nguy hiểm vì thông thường sao chép một cái gì đó sẽ không sửa đổi nó. Tác giả của class / struct dễ dàng bỏ qua việc giải phóng con trỏ khi suy luận về các bất biến và trạng thái, và do đó vô tình cố gắng bỏ qua con trỏ thông minh trong khi rỗng, hoặc không vẫn có quyền truy cập / quyền sở hữu dự kiến đối với dữ liệu trỏ đến.
auto_ptr không thể được sử dụng trong vùng chứa STL vì nó có một phương thức khởi tạo sao chép không đáp ứng yêu cầu của vùng chứa CopyConstructible . unique_ptr không triển khai một phương thức khởi tạo sao chép, vì vậy các vùng chứa sử dụng các phương thức thay thế. unique_ptr có thể được sử dụng trong vùng chứa và nhanh hơn cho các thuật toán std so với shared_ptr.
#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>
using namespace std;
int main() {
cout << boolalpha;
cout << "is_copy_constructible:" << endl;
cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;
vector<int> i_v;
i_v.push_back(1);
cout << "i_v=" << i_v[0] << endl;
vector<int> i_v2=i_v;
cout << "i_v2=" << i_v2[0] << endl;
vector< unique_ptr<int> > u_v;
u_v.push_back(unique_ptr<int>(new int(2)));
cout << "u_v=" << *u_v[0] << endl;
//vector< unique_ptr<int> > u_v2=u_v; //will not compile, need is_copy_constructible == true
vector< unique_ptr<int> > u_v2 =std::move(u_v); // but can be moved
cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;
vector< shared_ptr<int> > s_v;
shared_ptr<int> s(new int(3));
s_v.push_back(s);
cout << "s_v=" << *s_v[0] << endl;
vector< shared_ptr<int> > s_v2=s_v;
cout << "s_v2=" << *s_v2[0] << endl;
vector< auto_ptr<int> > a_v; //USAGE ERROR
return 0;
}
>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
vector< auto_ptr<int> > a_v; //USAGE ERROR
^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3