簡體   English   中英

函數中的C ++ auto_ptr(作為參數和返回值)

[英]C++ auto_ptr in functions (as argument and return value)

我試圖在我的代碼中使用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之后,Class對象存在,因此通過調用s.GetModelMean(Class),Class不為空。 但退出函數GetM后,Class為空,因此不再可用。 調用Draw函數時發生崩潰。

我按以下方式聲明了這些函數:

int GetM(auto_ptr<ClassType> aM); 

似乎班級被摧毀了,但我不明白為什么......

你不要給auto_ptr作為函數的參數。 要么:

int GetM(const auto_ptr<ClassType>&)

要么

int GetM(ClassType&)

要么

int GetM(ClassType*)

(也可能與const - 取決於你正在做什么)。 第一個你會用同樣的方式調用,第二個函數你會這樣調用:

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不允許你像那樣亂用它(因為不允許復制它 - 這更有意義)。

auto_ptr有一個“神奇的”復制構造函數,它與源對象混淆。 通過按值將參數傳遞給函數,可以觸發對復制構造函數的調用,並將原始auto_ptr保留為不指向任何內容的狀態。

打電話的原因

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簽名,以便它采用普通指針。

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由此臨時對象初始化。

暫無
暫無

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

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