2012-07-12 32 views
2

我想在我的代碼中使用auto_ptr,但顯然出現了問題。函數中的C++ auto_ptr(作爲參數和返回值)

auto_ptr<ClassType> Class(s.Build(aFilename)); //Instantiation of the Class object 
int vM = s.GetM(Class); 
int vS = s.Draw(Class); 

奇怪的是,類的實例化後,Class對象存在,因此 通過調用s.GetModelMean(類),級不爲空。但是在退出函數GetM後, 類爲空,因此不再可用。調用函數Draw時發生崩潰。

我聲明的功能方式如下:

int GetM(auto_ptr<ClassType> aM); 

看來,該類被破壞,但我不明白爲什麼...

回答

5

你大聲不要將auto_ptr作爲參數給一個函數。無論是做:

int GetM(const auto_ptr<ClassType>&) 

int GetM(ClassType&) 

int GetM(ClassType*) 

(可能也與常量 - 取決於你用它做什麼)。第一個你會以同樣的方式調用,第二個功能,你會這樣稱呼:

int vM = s.GetM(*Class.get()) 

最後沒有明星。

原因是:GetM將複製auto_ptr(不是Class對象)並在返回時銷燬auto_ptr。 auto_ptr(它是一個範圍指針或唯一指針 - 不是引用計數器!)將比銷燬Class。

無論如何:auto_ptr非常壞。只要有可能(你的編譯器已經支持C++ 11的一些小部分),使用std :: unique_ptr和std :: shared_ptr(最後一個引用計數)。 unique_ptr不會讓你像這樣混淆它(因爲不允許複製它 - 哪個imho更有意義)。

+0

謝謝,它甚至沒有使用* Class.get(),我剛剛通過類,它的工作。 – ISTB 2012-07-12 06:39:42

+2

我不同意'auto_ptr'非常壞 - 我認爲它只是一個誤導性的名字,所以它的功能已經被打破。 – 2012-07-12 06:46:01

+1

複製auto_ptr時,原始設置爲零,因此一次只有一個auto_ptr對象控制指針。這是在傳遞auto_ptr作爲函數參數時發生的情況。它是這樣設計的,並不意味着它被打破了。 – deo 2012-07-12 07:04:31

1

的auto_ptr有食堂一個「神奇」的拷貝構造函數與源對象。通過將值傳遞給函數,可以觸發調用以複製構造函數,並使原始auto_ptr保持其指向無狀態的狀態。

+0

謝謝,我懷疑這一點。所以我應該通過引用傳遞,但如何正確使用aout指針呢? – ISTB 2012-07-12 06:34:50

0

的原因,調用

int GetM(auto_ptr<ClassType> aM); 

自毀給定對象是auto_ptr複製對象時,有一個相當令人驚訝的行爲;它不僅修改了目標對象,還修改了對象的源代碼。如果你這樣做

std::auto_ptr<int> y = x; // modifies x *and* y 

存儲在x指針做的是移動yx設置爲null)。

這意味着std::auto_ptr非常不適合傳遞值或將它們存儲在容器中(因爲容器傾向於在內部複製對象)。它適合確保某些對象在退出某個作用域時被破壞 - 例如爲了使代碼異常安全。因此,有像

void f() { 
    std::auto_ptr<int> x = new int; 
    ... 
    // no need to delete anything, destroying 'x' will delete 
} 

或者

class Widget { 
public: 
    Widget() : m_myData(new int) { } 

private: 
    Widget(const Widget &other); // disabled 
    void operator=(const Widget &other); // disabled 

    std::auto_ptr<int> m_myData; 
}; 

東西實際上是罰款,可以簡化代碼。

擁有std::auto_ptr意味着擁有所有權。所以在你的具體情況下,我建議調整GetM簽名,以便它有一個簡單的指針。

0

auto_ptr使用一個小竅門,以便無論何時「複製」A到B,B獲取對象和A被清除。您可以使用它來非常清楚地聲明所有權傳遞語義(來源:Scott Meyers和Andrei Alexandrescus書籍。順便說一句,如果您想了解更多信息,請閱讀Effective C++)。

當然,如果可能的話,您應該使用unique_ptr(可以將它放在向量中!)從C++ 0x或從Boost而不是auto_ptr,因爲auto_ptr已棄用。

如果您對這些技巧細節感興趣,請注意,沒有魔術複製構造函數。根本沒有拷貝構造函數。複製構造函數需要const引用,並且您將無法清除複製的對象。所以當你寫

std::auto_ptr<A> a1(new A); 
std::auto_ptr<A> a2(a1); 

a1首先被鑄造到一些臨時對象。轉換運算符采用非const引用並清除a1。然後a2被這個臨時對象初始化。