2009-06-24 25 views
14

Khi làm việc với con trỏ và tham chiếu trong C++, đôi khi rất khó để biết con trỏ có quyền sở hữu dữ liệu được tham chiếu hay không. Ví dụ:Cách làm cho quyền sở hữu dữ liệu rõ ràng trong C++

Instance* i = new Instance(); 
Instance* j = i; 

Làm cách nào để xác định 2 con trỏ có quyền sở hữu đối tượng này? Nói cách khác, làm thế nào để làm rõ ràng trên đó con trỏ xóa phải được gọi là?

Lưu ý: Trong ví dụ trên, điều này không khó thấy vì đây là đoạn mã rất ngắn. Tuy nhiên, khi con trỏ được nhân đôi và truyền xung quanh rất nhiều, điều này có thể trở nên không rõ ràng.

+3

câu hỏi của bạn không có ý nghĩa. không có tham chiếu nào có 'quyền sở hữu'. Cả hai đều là tài liệu tham khảo có giá trị ngang nhau –

+0

Đó chính xác là vấn đề của tôi, và tôi tự hỏi làm thế nào tốt nhất để ghi lại con trỏ nào có trách nhiệm xóa cá thể đó. I'dd giống như một tính năng ngôn ngữ cho điều này, mặc dù tôi không có một đầu mối làm thế nào điều này có thể được thực hiện. –

+0

+1 Tại sao bạn downvoting câu hỏi này? – ralphtheninja

Trả lời

7

Bạn không thể xác định chủ sở hữu vì không có cơ chế tích hợp để biết con trỏ nào đang sở hữu bộ nhớ mà con trỏ trỏ đến.

Nếu bạn thực sự lo ngại về điều này, bạn luôn có thể giới thiệu quy ước đặt tên của riêng bạn, ví dụ: thông qua một số trước/sau sửa chữa cho tên biến của bạn. Nói cách khác, đó là thiết kế mã của bạn có thể cung cấp cho bạn thông tin này. Vì bạn (và đồng nghiệp của bạn) đang viết mã, bạn luôn có thể đảm bảo rằng thiết kế này được thực thi trong khi triển khai. Điều này tất nhiên có nghĩa là mọi người phải tuân theo các "quy tắc" này.

Đây là một lý do tại sao quy ước mã hóa phổ biến là rất quan trọng. Vì vậy, bạn có thể đọc mã của riêng bạn và người khác và hiểu nó.

7

Thứ nhất, có vẻ như không cần thiết phải gây nhầm lẫn khi sử dụng tham chiếu để tham chiếu đến dữ liệu phải bị xóa. Sử dụng một con trỏ để thay thế.

Thứ hai, nếu bạn muốn chỉ định quyền sở hữu đối tượng, hãy sử dụng lớp trình bao bọc quản lý quyền sở hữu. Có auto_ptr dành riêng cho mục đích này, mặc dù nó có những thiếu sót. (Những điều này nên được giải quyết bởi unique_ptr trong phiên bản tiếp theo của ngôn ngữ, mặc dù điều đó không giúp bạn bây giờ).

Thứ ba, trong trường hợp đơn giản nhất (thường xuyên nhất có thể), không sử dụng trực tiếp heap. Chỉ cần khai báo một đối tượng địa phương, ví dụ:

std::vector<int> v; 

Điều này không ngăn bạn chuyển quyền sở hữu khi cần (sử dụng swap).

+0

Đây chỉ là một ví dụ. Khi sử dụng đa hình, nó là cần thiết. –

+1

Tôi sử dụng đa hình mọi lúc trong C++. Tôi chưa bao giờ thấy cần thiết. –

+4

Nó không phải là cần thiết để sử dụng một tài liệu tham khảo cho đa hình. Một con trỏ hoạt động tốt. Nếu bạn có một tham chiếu đến một đối tượng, nó giống như nói "Dù bạn làm gì, đừng xóa cái này!" Với một con trỏ, nó mở rộng hơn để bị xóa (mặc dù vẫn đòi hỏi một sự hiểu biết về thiết kế/quyền sở hữu). –

3

Bạn có thể sử dụng một cái gì đó như shared_ptr<> để chia sẻ quyền sở hữu một cách rõ ràng. Nếu bạn muốn duy trì một chủ sở hữu duy nhất rõ ràng với con trỏ không sở hữu khác đề cập đến cùng một đối tượng, bạn có thể sử dụng giống như boost::scoped_ptr<> cho con trỏ sở hữu và có một typedef cho phi sở hữu con trỏ:

typedef Instance* UnownedInstance_ptr; // or some better name 

sẽ này ít nhất là ý định tài liệu. Tôi không biết cách nào trên đỉnh đầu để có một kiểu con trỏ thông minh ngăn cản khả năng xóa con trỏ chứa và ngăn việc sao chép con trỏ vào một con trỏ thông minh khác chiếm quyền sở hữu (vì nguồn không có bất kỳ quyền sở hữu để cho đi), nhưng đó có thể là một lớp học thú vị để đại diện cho chính sách đó.

3

Đối với tôi, tôi sẽ đi với Ký hiệu Hungary!

Joel cho bạn biết phần còn lại :: Making Wrong Code Look Wrong

một ví dụ trong trường hợp của bạn ::

Instance* Owener_i = new Instance(); 
Instance* Observer_j = i; 
. 
. 
. 
. 
. 
delete Observer_j; // Wrong! not an Owner. 
2

Như những người khác chỉ ra - sử dụng một quy ước. Tôi sử dụng con trỏ thô cho các biến không sở hữu, và chủ sở hữu thường được đưa vào một số loại con trỏ thông minh (chẳng hạn như boost :: scoped_ptr) hoặc thậm chí không phải là một con trỏ ở tất cả mà là một đối tượng được tạo trên ngăn xếp.

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