2012-06-18 27 views
5

Giả sử tôi có nhu cầu làm như sau (Đây chỉ là một số mã tưởng tượng để thảo luận về tiêu chuẩn C++, vì vậy tôi sẽ không thảo luận tại sao tôi thiết kế nó theo cách này, vì vậy đừng làm phiền tôi với điều gì đó như: thiết kế của bạn là sai.)Cùng một địa chỉ, nhiều shared_ptr quầy, là nó bị cấm bởi C + + tiêu chuẩn?

T* ptr = new T; 
shared_ptr<T> p(ptr); 
shared_ptr<T> q(ptr, SomeDeleterThatDoesnotDeleteButDoSomeOtherStuff()); 

Giả logic đảm bảo rằng p hoặc một số bản sao của nó sống lâu hơn tất cả các bản sao của q, vì vậy hầu như sẽ không có bất kỳ vấn đề. Câu hỏi của tôi là, nó bị cấm bởi tiêu chuẩn C++, ví dụ: tuyên bố rõ ràng như UB theo tiêu chuẩn C++, cho các shared_ptr quầy khác nhau để chia sẻ cùng một địa chỉ?

Cảm ơn.

+1

Nếu bạn 'trả lại q;' thì sao? –

+0

@Peter Tôi nghĩ rằng đó là ý tưởng - để gọi người không deleter và làm một cái gì đó hữu ích với kiến ​​thức rằng một số tập con của tài liệu tham khảo bây giờ là sản phẩm nào. – Potatoswatter

+0

Thiết kế không phải là * khủng khiếp vì mục đích của nó. Bạn có thể đảm bảo sự hủy diệt thích hợp bằng cách thay thế deleter tùy chỉnh bằng cách xóa *, và cũng có thể sở hữu 'shared_ptr' của riêng nó thành một đối tượng giả để thực hiện hành động trong destructor của nó hoặc 2. có một deleter tùy chỉnh khác thực hiện hành động . Nhưng những phương pháp đó có thể kém hiệu quả hơn, nếu các bộ (các) đối tượng 'q' thay đổi nhanh chóng so với tập hợp các chủ sở hữu thích hợp' p'. – Potatoswatter

Trả lời

2

Tôi không thể tìm thấy bất kỳ điều gì trong tiêu chuẩn (tốt, bản nháp cuối cùng) quy định cụ thể nó. Gần nhất tôi có thể tìm thấy một lưu ý trong 20.9.11.2.10 shared_ptr casts

5 [Lưu ý: dường như tương đương với biểu shared_ptr (static_cast (r.get())) cuối cùng sẽ dẫn đến hành vi không xác định, cố gắng để xóa cùng một đối tượng hai lần. —end lưu ý]

mà thực sự có vẻ như quên trường hợp của bạn với một deleter tùy chỉnh.

5

Nếu đối tượng shared_ptr đầu tiên bị hủy, sau đó bạn nhận UB do các đối tượng sử dụng đối tượng thứ hai có thể truy cập đối tượng được phát hành.

Vì bạn đảm bảo rằng đối tượng shared_ptr đầu tiên của bạn sống lâu hơn, thứ hai, bạn không nhận được UB.

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