2013-06-03 37 views
29

Tôi cố gắng hiểu cách std::unique_ptr hoạt động và để tìm tài liệu this. Tác giả bắt đầu từ ví dụ sau:Làm thế nào để khai báo std :: unique_ptr và việc sử dụng nó là gì?

#include <utility> //declarations of unique_ptr 
using std::unique_ptr; 
// default construction 
unique_ptr<int> up; //creates an empty object 
// initialize with an argument 
unique_ptr<int> uptr (new int(3)); 
double *pd= new double; 
unique_ptr<double> uptr2 (pd); 
// overloaded * and -> 
*uptr2 = 23.5; 
unique_ptr<std::string> ups (new std::string("hello")); 
int len=ups->size(); 

gì là khó hiểu với tôi là trong dòng này

unique_ptr<int> uptr (new int(3)); 

Chúng tôi sử dụng số nguyên như là một đối (giữa dấu ngoặc tròn) và đây

unique_ptr<double> uptr2 (pd); 

chúng tôi đã sử dụng con trỏ làm đối số. Liệu nó có bất kỳ sự khác biệt?

Điều gì cũng không rõ ràng đối với tôi, là cách con trỏ, được khai báo theo cách này sẽ khác với con trỏ được khai báo theo cách "bình thường".

+4

'new int (3)' trả về một con trỏ tới 'int' mới, giống như' pd' là một con trỏ tới 'double' mới. –

Trả lời

3

Con trỏ duy nhất được đảm bảo sẽ bị hủy khi bạn đi ra khỏi phạm vi. http://en.cppreference.com/w/cpp/memory/unique_ptr

Trong trường hợp:

unique_ptr<double> uptr2 (pd); 

pd sẽ bị phá hủy khi bạn đi ra khỏi phạm vi. Điều này tạo điều kiện quản lý bộ nhớ bằng cách xóa tự động.

sau đó trường hợp của unique_ptr<int> uptr (new int(3)); là không khác nhau ngoại trừ việc con trỏ thô không được gán cho bất kỳ biến đây

35

Các constructor của unique_ptr<T> chấp nhận một con trỏ liệu đến một đối tượng kiểu T (do đó, nó chấp nhận một T*).

Trong ví dụ đầu tiên:

unique_ptr<int> uptr (new int(3)); 

Con trỏ là kết quả của một biểu thức new, trong khi ở ví dụ thứ hai:

unique_ptr<double> uptr2 (pd); 

Con trỏ được lưu trữ trong biến pd.

Về mặt lý thuyết, không có gì thay đổi (bạn đang xây dựng một unique_ptr từ một con trỏ thô), nhưng cách tiếp cận thứ hai là nguy hiểm hơn, vì nó sẽ cho phép bạn, ví dụ, để làm:

unique_ptr<double> uptr2 (pd); 
// ... 
unique_ptr<double> uptr3 (pd); 

Như vậy có hai các con trỏ độc đáo có hiệu quả đóng gói cùng một đối tượng (do đó vi phạm ngữ nghĩa của con trỏ độc đáo).

Đây là lý do tại sao biểu mẫu đầu tiên để tạo con trỏ duy nhất tốt hơn, khi có thể. Lưu ý rằng trong C++ 14, chúng tôi sẽ có thể thực hiện:

unique_ptr<int> p = make_unique<int>(42); 

Điều này rõ ràng hơn và an toàn hơn.Bây giờ liên quan đến nghi ngờ này của bạn:

What is also not clear to me, is how pointers, declared in this way will be different from the pointers declared in a "normal" way.

con trỏ thông minh có nghĩa vụ phải mô hình sở hữu đối tượng, và tự động chăm sóc phá hủy các đối tượng nhọn khi người cuối cùng (thông minh, sở hữu) con trỏ đến đối tượng mà rơi ra khỏi phạm vi. Bằng cách này bạn không cần phải nhớ làm delete trên các đối tượng được phân bổ động - destructor của con trỏ thông minh sẽ làm điều đó cho bạn - cũng không phải lo lắng về việc bạn sẽ không dereference một con trỏ (lơ lửng) đến một đối tượng đã bị phá hủy đã:

{ 
    unique_ptr<int> p = make_unique<int>(42); 
    // Going out of scope... 
} 
// I did not leak my integer here! The destructor of unique_ptr called delete 

Bây giờ unique_ptr là một con trỏ thông minh rằng các mô hình sở hữu độc đáo, có nghĩa là bất cứ lúc nào trong chương trình của bạn có phải chỉ một (sở hữu) con trỏ đến đối tượng nhọn - đó là lý do tại sao unique_ptr không thể sao chép được. Miễn là bạn sử dụng con trỏ thông minh theo cách không phá vỡ hợp đồng ngầm mà họ yêu cầu bạn tuân thủ, bạn sẽ có bảo đảm rằng không có bộ nhớ nào bị rò rỉ và chính sách quyền sở hữu thích hợp cho đối tượng của bạn sẽ là thực thi. Con trỏ thô không cung cấp cho bạn đảm bảo này.

+2

Xin chào, tôi không thể hiểu bất kỳ điều gì về 'quyền sở hữu đối tượng mô hình',' số nguyên bị rò rỉ' trong mã hoặc 'thực thi chính sách quyền sở hữu đối với đối tượng'. Bạn có thể đề xuất các chủ đề/tài nguyên để tìm hiểu các khái niệm này không? –

+0

Tôi không thể sử dụng 'unique_ptr', mà không nhận được một lỗi:' Văn bản ">" là không mong muốn. Có thể là mã thông báo này được dự định là một trình kết thúc danh sách đối số mẫu nhưng tên không được biết là mẫu.', mặc dù tôi có '#include ' và '#include '. Lời khuyên nào? – Anonymous

2

Không có sự khác biệt nào trong cả hai khái niệm gán cho unique_ptr.

int* intPtr = new int(3); 
unique_ptr<int> uptr (intPtr); 

cũng tương tự như

unique_ptr<int> uptr (new int(3)); 


how pointers, declared in this way will be different from the pointers declared in a "normal" way.

Nếu bạn tạo một số nguyên trong không gian đống (sử dụng mới từ khóa hoặc malloc), sau đó bạn sẽ phải tự xóa bộ nhớ đó (sử dụng xóa hoặc miễn phí tương ứng).

Trong đoạn mã dưới đây,

int* heapInt = new int(5);//initialize int in heap memory 
. 
.//use heapInt 
. 
delete heapInt; 

Ở đây, bạn sẽ phải xóa heapInt, khi nó được thực hiện sử dụng. Nếu nó không bị xóa, thì rò rỉ bộ nhớ sẽ xảy ra.
Để tránh rò rỉ bộ nhớ như vậy unique_ptr được sử dụng, trong đó unique_ptr tự động xóa không gian bị chiếm bởi heapInt khi nó nằm ngoài phạm vi.