2009-09-09 74 views
7

Tài liệu tham khảo trong C++ là một cấu trúc conveneint cho phép chúng tôi để đơn giản hóa mã C sau:shared_ptr và tài liệu tham khảo trong C++

f(object *p){ 
    //do something 
} 

int main(){ 
    object* p = (object*) calloc(sizeof(object)); 
    f(p); 
} 

để

f(object& o){ 
    //do something 
} 

int main(){ 
    object o = object(); 
    f(o); 
} 

con trỏ chung được một sự tiện lợi trong C++ đơn giản hóa bộ nhớ sự quản lý. Tuy nhiên, tôi không chắc chắn làm thế nào để vượt qua một shared_ptr đến một chức năng như f(object& o) chấp nhận đối số bằng cách tham chiếu?

f(object& o){ 
    //do something 
} 

int main(){ 
    shared_ptr<object> p (new object()); 
    f(*p); 
} 

Con trỏ chia sẻ có tăng lên khi đối tượng được truyền qua tham chiếu đến hàm không?

+2

Thay vì 'object * p = (đối tượng *) calloc (sizeof (đối tượng));' bạn nên sử dụng 'object * p = new object();' do đó hàm tạo được gọi! (Hoặc bạn có thể 'calloc' sau đó vị trí-'new'.) – strager

+1

Bạn nên chờ một vài giờ để cung cấp cho mọi người thời gian để tìm và trả lời câu hỏi của bạn, hoặc bạn sẽ đi ném trả lời-shuffle, và mọi người sẽ không có một cơ hội để cải thiện câu trả lời của họ thông qua phản hồi nhận xét. Sau khi bạn nghĩ rằng bụi đã lắng xuống, hãy chọn câu trả lời hữu ích nhất. – GManNickG

+0

Sẽ có ý nghĩ đó trong tương lai. Cảm ơn! – dzhelil

Trả lời

10

Hãy shared_ptr theo giá trị và số lượng tài liệu tham khảo sẽ tăng lên. Điều này dễ dàng hơn khi bạn typedef nó:

typedef boost:shared_ptr<object> object_ptr; 

void foo(object_ptr obj) 
{ 
    obj->/* stuff*/; 
    obj.reset(); //only resets this local copy, that means: 
       // reduce reference count (back to 1), and 
       // set obj to point at null. 
} 

int main(void) 
{ 
    object_ptr obj(new object()); 
    foo(obj); 
} 

Xin lưu ý rằng tham chiếu là bí danh. Khi bạn chuyển qua tham chiếu, bạn không truyền con trỏ, bản sao, v.v ..., bạn đang bí danh một đối tượng khác. (Trên thực tế chúng được thực hiện như con trỏ):

typedef boost:shared_ptr<object> object_ptr; 

void foo(object_ptr& obj) 
{ 
    obj.reset(); // the references was never increased, since a copy has not 
       // been made, this *is* obj in main. so the reference 
       // goes to 0, and obj is deleted 
} 

int main(void) 
{ 
    object_ptr obj(new object); 
    foo(obj); // after this, obj has been reset! 
} 

Luôn luôn nhớ là const đúng, để ngăn chặn các lỗi:

typedef boost:shared_ptr<object> object_ptr; 

void foo(const object_ptr& obj) 
{ 
    obj.reset(); // cannot do! 
} 

int main(void) 
{ 
    object_ptr obj(new object); 
    foo(obj); 
} 

Tôi nghĩ rằng bạn nên thích để vượt qua con trỏ thông minh như tài liệu tham khảo khi có thể, để tránh gia tăng không liên quan và giảm (và bản sao và không có điều gì).

+3

... và tránh truyền con trỏ thông minh làm đối số nếu chức năng không thực sự cần con trỏ thông minh (tức là nó không tạo bản sao để sử dụng sau này). –

2

Con trỏ được chia sẻ có tăng lên khi đối tượng của nó được chuyển qua tham chiếu đến hàm không?

Không, khi bạn đang truy cập con trỏ thô rồi chuyển nó. Bạn muốn làm một cái gì đó tương tự như sau:

f(shared_ptr<object> o){ 
    //do something 
} 

int main(){ 
    shared_ptr<object> p (new object()); 
    f(p); 
} 
-1

Trước tiên, từ quan điểm chức năng, tham chiếu trong C++ giống hệt như con trỏ. Họ chỉ lý do họ đã được thêm vào ngôn ngữ là để làm cho cú pháp của quá tải nhà điều hành được tự nhiên hơn. (Ví dụ: để cho phép một người viết một + b thay vì & a + & b)

Mẫu mã C và C++ của bạn hoàn toàn không tương đương. Phiên bản C của C++ của bạn sẽ là:

f(object *p){ 
    //do something 
} 

int main(){ 
    object o; 
    object_constructor(&o); 
    f(&o); 
    object_destructor(&o); 
} 

Trong thực tế, đây là loại mã C++ biên dịch khái niệm sẽ tạo ra.

Liên quan đến câu hỏi thứ hai của bạn: Có, đó là cách chính xác để gọi hàm f. Bộ đếm con trỏ dùng chung sẽ không được tăng lên. Con trỏ thực tế đến đối tượng sẽ được truyền, như thể bạn không sử dụng shared_ptr. Đó là an toàn tuy nhiên, miễn là f không làm bất cứ điều gì sôi nổi. Chỉ cần nhớ rằng cùng một điều chính xác đang xảy ra như thể tham số của f lấy một con trỏ thay vì một tham chiếu. Sự khác biệt duy nhất là trình biên dịch tự động chuyển địa chỉ của biến mà không cần phải sử dụng rõ ràng toán tử &.

Cá nhân tôi không thích bao giờ chuyển biến theo tham chiếu (đi qua tham chiếu const là ok). Thay vào đó, tôi thích sử dụng con trỏ vì nó làm cho nó rõ ràng hơn tại trang gọi mà hàm mà chúng ta đang gọi có khả năng sửa đổi đối số của nó (vì biểu tượng & hiển thị tại trang gọi).

Hòa bình

+2

Xin lỗi, nhưng "tham chiếu trong C++ giống hệt như con trỏ" là sai. Ngoài ra, có lẽ nó chỉ là phong cách nhưng tôi nghĩ rằng hầu hết các lập trình viên C++ sẽ đồng ý đi qua con trỏ thay vì tài liệu tham khảo là ngớ ngẩn. Bây giờ bạn phải kiểm tra null tất cả thời gian. Tài liệu tham khảo tự nhiên hơn. – GManNickG

1
f(object& o){ 
    //do something 
} 

int main(){ 
    shared_ptr<object> p (new object()); 
    f(*p); 
} 

con trỏ chia sẻ sẽ được tăng lên khi đối tượng của nó được thông qua tham khảo đến một chức năng?

Trong mã ở trên - không. p sẽ có bộ đếm tham chiếu bằng 1 ở mọi thời điểm. Bạn có thể xác minh điều này trong trình gỡ lỗi. Bộ đếm tham chiếu của shared_ptr đếm số lượng các cá thể shared_ptr trỏ đến cùng một đối tượng, nó không theo dõi các tham chiếu mà bạn tạo bằng cách gọi toán tử *(). Và nó không phải - kể từ khi p được đảm bảo tồn tại cho đến khi kết thúc phạm vi và cuộc gọi hàm nằm trong cùng phạm vi này (hoặc sâu hơn) p sẽ có trong toàn bộ cuộc gọi tới f (). Vì vậy, mọi thứ đều ổn.

... trừ khi trong f bạn lấy địa chỉ của o và lưu trữ ở đâu đó rằng sẽ kéo dài sau khi f lợi nhuận. Điều này bạn nên tránh bằng mọi cách - chuyển shared_ptr nếu bạn cần làm điều đó.

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