繁体   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