![](/img/trans.png)
[英]How to avoid returning handles to object internals - Item 28 Effective C++
[英]Is this an error in “More Effective C++” in Item28?
在閱讀更有效的C ++中的item28時遇到一個問題。 在此項目中,作者向我們展示了我們可以在SmartPtr
使用成員模板,以便將SmartPtr<Cassette>
轉換為SmartPtr<MusicProduct>
。
以下代碼與書中的代碼不同,但是具有相同的效果。
#include <iostream>
class Base {};
class Derived : public Base {};
template<typename T>
class smart {
public:
smart(T* ptr)
: ptr(ptr)
{}
template<typename U>
operator smart<U>()
{
return smart<U>(ptr);
}
~smart()
{
delete ptr;
}
private:
T* ptr;
};
void test(const smart<Base>& ) {}
int main()
{
smart<Derived> sd(new Derived);
test(sd);
return 0;
}
它確實可以編譯而沒有編譯錯誤。 但是當我運行可執行文件時,我得到了一個核心轉儲。 我認為這是因為轉換運算符的成員函數使一個臨時智能,它具有指向sd
相同ptr的指針(其類型為smart<Derived>
)。 因此,刪除指令會運行兩次。 而且,調用test之后,我們將再也無法使用sd
了,因為sd
中的ptr
已經被刪除了。
現在我的問題是:
非常感謝您的幫助。
是的,您已經用代碼相當准確地描述了問題。
至於如何使它起作用:就像從淺表副本遇到問題時的通常情況一樣:進行深表副本。 也就是說,您不僅需要克隆指向相同數據的指針,還需要克隆數據,並使第二個對象指向數據的克隆,而不是原始數據。
或者,使用引用計數的指針,並在執行副本時增加引用計數,在銷毀副本時減少引用計數。 當計數達到零(而不是之前)時,刪除pointee數據。
一般來說:避免做所有這一切。 假設您使用的是相對最新的編譯器,則標准庫應該已經包含一個shared_ptr
和unique_ptr
,它們可以處理您的許多智能指針需求。
您的解釋是正確的,轉換運算符將創建一個不同的對象,該對象持有指向同一基礎對象的指針。 一旦超出范圍,它將被銷毀,並依次調用delete
。
不確定我是否理解最后一個問題,如果您要問的是這是否有用,那么如果正確實現,它將很有用。 例如,如果您使用的是std::shared_ptr
而不是原始指針並手動分配/刪除內存,那么它將正常工作。 在其他情況下,甚至可能沒有動態分配的對象……這只是一種工具,請在有意義的地方使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.