我在閱讀中的item28時遇到了一個問題更有效的C++。在這個項目中,作者向我們表明我們可以使用SmartPtr
中的成員模板,以使SmartPtr<Cassette>
可以轉換爲SmartPtr<MusicProduct>
。
以下代碼與本書中的代碼不同,但效果相同。這是Item28中「更有效的C++」中的錯誤嗎?
#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>
)。所以delete指令運行兩次。更重要的是,在通話測試後,我們再也不能使用sd
,因爲sd
中的ptr
已經被刪除。
現在我的問題是:
- 我的想法是對的嗎?或者我的代碼與書中的原始代碼不一樣?
- 如果我的想法是對的,有沒有辦法做到這一點?
非常感謝您的幫助。
您的代碼與本書中的原始代碼不同。本書中代碼的意圖是顯示智能指針即使是模板化的,它們可以繞過「Base」和「Derived」而成爲不同的類型,儘管它們在相同的類層次結構中。你的實現演示了這種類型轉換機制,但是在調用'delete'之前沒有引用計數檢查,它與智能指針不同,這使它更接近智能ptr正在做的事情:'〜smart(){if(reference_count_ <1)delete ptr ;}'。通常情況下,一些互斥鎖可以保護refcount檢查和'delete'之間的計數器。 –
哦,我明白你的意思了。原始代碼沒有顯示構造函數和析構函數的實現。我在測試代碼中錯誤地使用了'std :: auto_ptr'的ctor和dtor,它沒有引用計數,因此在這種情況下不適用。非常感謝。 – particle128