簡體   English   中英

這是Item28中“更有效的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_ptrunique_ptr ,它們可以處理您的許多智能指針需求。

您的解釋是正確的,轉換運算符將創建一個不同的對象,該對象持有指向同一基礎對象的指針。 一旦超出范圍,它將被銷毀,並依次調用delete

不確定我是否理解最后一個問題,如果您要問的是這是否有用,那么如果正確實現,它將很有用。 例如,如果您使用的是std::shared_ptr而不是原始指針並手動分配/刪除內存,那么它將正常工作。 在其他情況下,甚至可能沒有動態分配的對象……這只是一種工具,請在有意義的地方使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM