2010-01-20 97 views
6

Ưu điểm và nhược điểm của việc sử dụng con trỏ tự động (auto_ptr), so với con trỏ thông thường là gì? Tôi đã nghe nó tự động phát hành bộ nhớ nhưng làm thế nào đến nó không được sử dụng thường xuyên?Ưu điểm/nhược điểm của các con trỏ tự động

+3

Luật trừu tượng bị rò rỉ: http://www.joelonsoftware.com/articles/LeakyAbstractions.html –

+1

Lưu ý: std :: auto_ptr chỉ là một trong toàn bộ các con trỏ thông minh được sử dụng trong C++. –

+1

OK. Tôi hiểu bạn có câu hỏi tốt hơn bây giờ. Có std :: auto :: ptr là ít nhất được sử dụng, nhưng bạn không nên nhìn vào chúng trong sự cô lập. Chúng là một phần của bộ con trỏ thông minh và có cách sử dụng cụ thể của riêng chúng. Sử dụng tốt cho std :: auto_ptr là tài liệu chuyển quyền sở hữu. –

Trả lời

10

Hạn chế chính của std::auto_ptr là nó có giới hạn chuyển quyền sở hữu. Điều đó làm cho nó không thể lưu trữ std::auto_ptr trong các thùng chứa STL vì các thùng chứa sử dụng hàm tạo bản sao khi bạn lưu trữ hoặc lấy một phần tử.

Ngoài ra, một khía cạnh quan trọng khác mà tôi đã nhận thấy về std::auto_ptr là chúng không thể phân phối trong việc sử dụng các thành ngữ PIMPL. Điều này là bởi vì, họ yêu cầu định nghĩa đầy đủ về destructor của lớp bọc. Xem chủ đề this trên c.l.C++. M để thảo luận chi tiết hơn.

Cập nhật: Chuyển quyền sở hữu

class Test {}; 
std::auto_ptr<Test> ap_test_1(new Test); 
std::auto_ptr<Test> ap_test_2(new Test); 

ap_test_2 = ap_test_1; // here ap_test_1's ownership is transferred i.e. ap_test_2 is the 
         // new owner and ap_test_1 is NULL. 

Xem this chủ đề trên trang web của Herb Sutter để biết thêm chi tiết về những gì này có nghĩa là khi sử dụng trong một container STL được sử dụng bởi các thuật toán STL.

+0

Có, tôi nghĩ rằng điều này sẽ trả lời câu hỏi của tôi nhưng bạn có thể giải thích thêm về việc chuyển giao quyền sở hữu này không? – jasonline

+0

auto_ptr * có thể * được sử dụng cho pimpl; nó không chỉ đặc biệt tốt vì bạn phải khai báo và thực hiện một destructor. Tốt hơn để sử dụng boost :: scoped_ptr (hoặc shared_ptr) mà không yêu cầu định nghĩa dtor. – MattyT

+0

Tôi không gặp vấn đề gì khi sử dụng std :: auto_ptr cho PIMPL. –

6

Con trỏ thông minh được sử dụng thường xuyên trong C++, mặc dù có lẽ không thường xuyên như chúng cần. Các std::auto_ptr có một vài vấn đề (bạn không thể sử dụng nó trong bộ sưu tập thư viện chuẩn, ví dụ), nhưng có rất nhiều người khác. Phổ biến nhất trong số này là the ones that come with the Boost library và sẽ là một phần của tiêu chuẩn C++ tiếp theo - bạn nên xem qua.

Lưu ý rằng con trỏ thông minh chủ yếu là về quyền sở hữu và xóa đối tượng được tạo động. Nếu bạn không có các đối tượng tự động tạo ra, bạn thường không muốn con trỏ thông minh:

{ 
    int i = 42; 
    auto_ptr <int> p(& i); // bad! 
} 

Bạn thực sự không muốn làm điều này, như khi autopointer đi ra khỏi phạm vi, nó sẽ cố gắng xóa tôi. Thật không may, tôi đã không được tạo động, vì vậy những điều xấu sẽ xảy ra. Vì vậy, bạn cần cả hai loại con trỏ, thông minh và bình thường, trong hầu hết các chương trình C++.

+0

Có, tôi đã nghe nói về những người từ Boost. Nó chỉ là mối quan tâm cụ thể của tôi là những lý do tại sao nó không được sử dụng thường xuyên như con trỏ bình thường được sử dụng. – jasonline

+3

'auto_ptr' không được sử dụng thường xuyên vì trong hầu hết các trường hợp, những cái từ Boost là thích hợp hơn. Con trỏ thông minh * được sử dụng rất thường xuyên và ít nhất là trong số nhiều người lập trình, thường xuyên hơn con trỏ bình thường. Tại sao bạn nghĩ con trỏ bình thường thường được sử dụng hơn? – jalf

+0

@ jasonline: Trong mã C++ hiện đại, tôi hầu như không bao giờ thấy con trỏ bình thường. Con trỏ thông minh là tiêu chuẩn và con trỏ bình thường là rất nhiều ngoại lệ. Nếu bạn thấy bất kỳ mã nào có con trỏ thì rất đáng ngờ về tác giả. Thời gian duy nhất tôi nhìn thấy con trỏ bình thường (RAW) là trong mã demo là hướng dẫn cho giảng dạy sinh viên những gì con trỏ được. –

0

Auto_ptr có mô hình quyền sở hữu đối tượng mà đối tượng trỏ vào. Bạn không thể có nhiều refrence cho cùng một đối tượng, và bạn không thể đặt chúng trong stl container và như vậy - mã trông giống như nó thực sự chuyển quyền sở hữu, và sẽ gây ra khó khăn khó khăn để theo dõi lỗi trong sản xuất.

số tăng shared_ptr trong hầu hết các trường hợp thực tế hơn.

+0

Bạn cũng nên cẩn thận với Boost smartpointers :) – n0rd

+0

Nếu được sử dụng chính xác tại sao nó sẽ gây khó khăn để theo dõi vấn đề. std :: auto_ptr thực hiện chính xác những gì nó được dự định làm (không còn không kém). std :: tr1 :: shared_ptr là một kiểu con trỏ thông minh hoàn toàn khác. học cách sử dụng đúng loại con trỏ thông minh. –

+2

Tôi hy vọng bạn không bao giờ có một lỗi, bao giờ, Martin :) – Will

1

Đừng nhầm lẫn con trỏ tự động (std :: auto_ptr) với họ của con trỏ thông minh (đáng chú ý là std :: auto_ptr, boost :: scoped_ptr và boost :: shared_ptr).

Tôi khá nhiều không bao giờ sử dụng con trỏ tự động bởi vì, hầu hết thời gian, tôi muốn sử dụng tài liệu tham khảo. Thời gian duy nhất khi tôi làm là cho các biến thành viên mà không thể được khởi tạo trong constructor của đối tượng.

Ngược lại, con trỏ thông minh là rất mạnh mẽ, nhưng đó không phải là câu hỏi của bạn, tôi đoán :)

1

Những lợi thế là sử dụng đơn giản, họ làm công việc của họ.

void foo() { 
    std::auto_ptr<int> bar(new int); 
    // do the stuff that potentially throw 

} // the auto_ptr destructor will call delete here 

Bất lợi là ngay sau khi bạn thoát khỏi việc sử dụng đơn giản này, bạn nhấn vào ngữ nghĩa xấu của auto_ptr.

std::auto_ptr<int> foo(new int); 
std::auto_ptr<int> bar = foo; // foo is changed here! It does not have ownership anymore. 

Bạn nên sử dụng unique_ptr và shared_ptr có ngữ nghĩa tốt, và có sẵn trong boost ::, và sẽ có sẵn trong std :: trong C++ tiếp theo tiêu chuẩn

0

Câu chuyện ngắn: std :: auto_ptr không thể được chia sẻ, con trỏ thông thường có thể.

Và sau đó có Boost.SmartPointer

1

Có lẽ lý do lớn nhất tại sao nó không được sử dụng rộng rãi:

Các std :: auto_ptr có một bất lợi to lớn: Nó không thể được sao chép mà không phá hủy. Khi bạn cần tạo một bản sao của một con trỏ tự động, thể hiện ban đầu sẽ bị hủy. Điều này có nghĩa là bạn chỉ có thể có một bản sao của đối tượng bất kỳ lúc nào. Điều này cũng có nghĩa là không thể sử dụng auto_ptr với các vùng chứa tiêu chuẩn, chẳng hạn như vector, deque, list, set và map. Trong thực tế, nó khó có thể được sử dụng trong bất kỳ lớp nào dựa vào xây dựng bản sao.

Hơn nữa, auto_ptr không an toàn vì không có gì ngăn bạn vô tình sao chép. Và nếu bạn làm như vậy, bạn sẽ hủy bản gốc. Ngoài ra, một số trình biên dịch C++ tương thích chuẩn ít hơn cho phép bạn lưu trữ các đối tượng được khai báo chuyển tiếp trong một auto_ptr và sử dụng nó mà không bao giờ bao gồm định nghĩa đầy đủ của lớp đó. Điều này luôn dẫn đến rò rỉ bộ nhớ.

1

Chính raison d'être cho auto_ptr là chuyển quyền sở hữu một cách ngoại lệ an toàn. Mặc dù hầu hết mọi người sử dụng nó như là một người đàn ông nghèo của tăng :: scoped_ptr.

Cách sử dụng chính là cho các hàm trả về bằng cách sử dụng con trỏ đối tượng làm tham số hoặc giá trị trả lại.

Ví dụ một chức năng nhà máy

std::auto_ptr<MyClass> createMyClass(MyClass::Type type) { 
    if (type == MyClass::TypeOne) { 
     return std::auto_ptr(new MyClassOne); 
    } 
    else { 
     return std::auto_ptr(new MyClassTwo); 
    } 
} 


void foo() { 
    std::auto_ptr<MyClass> myc = createMyClass(MyClass::TypeOne); 

    // use myc 
} 

Trong khi mã này là rất đơn giản và không có trường hợp ngoại lệ nên được ném nếu trường hợp ngoại lệ được ném myc xử lý nó một cách chính xác, nơi làm điều này với con trỏ thô sẽ rất khó.

boost :: shared_ptr cũng có thể được sử dụng, nhưng điều này cung cấp nhiều chức năng hơn yêu cầu nó cũng cho biết bạn mong muốn đối tượng được chia sẻ. Trường hợp với auto_ptr đơn giản hơn và bạn đang nói rõ rằng bạn đang chuyển quyền sở hữu.

Gần đây tôi đã được thông báo về tăng :: unique_ptr có vẻ giống như sử dụng auto_ptr mà không có những hạn chế.

thấy best practice when returning smart pointers để biết thêm

0

Các auto_ptr có thể used for multiple purposes, nhưng tôi nghĩ đó là sử dụng tốt nhất là một công cụ để phân bổ đối tượng trên heap và họ có cho deallocated khi phạm vi ngăn xếp khung được kết thúc.

IMHO chỉ thực sự vấn đề với auto_ptr mới là tên. Mọi người nhìn vào nó và nghĩ rằng đó là một con trỏ thông minh, tất nhiên là không.

Nếu chúng tôi gọi nó là một cái gì đó như AutoDelete<T> có lẽ chúng tôi sẽ có các loại thảo luận khác nhau.:-)

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