函数中的C ++ auto_ptr(作为参数和返回值)

时间:2012-07-12 06:28:27

标签: c++ auto-ptr

我正在尝试在我的代码中使用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功能后, 类是空的,因此不再可用。调用Draw函数时发生崩溃。

我按以下方式声明了这些功能:

int GetM(auto_ptr<ClassType> aM); 

似乎课程被毁了,但我不明白为什么......

4 个答案:

答案 0 :(得分:6)

你大喊不要将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不允许你像那样乱用它(因为不允许复制它 - 这更有意义)。

答案 1 :(得分:1)

auto_ptr有一个“神奇的”复制构造函数,它与源对象混淆。通过按值将参数传递给函数,可以触发对复制构造函数的调用,并将原始auto_ptr保留为指向任何位置的状态。

答案 2 :(得分:0)

调用

的原因
int GetM(auto_ptr<ClassType> aM); 

析构给定的对象是auto_ptr在复制对象时有相当令人惊讶的行为;它不仅修改目标对象,还修改对象。如果你这样做

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

存储在x中的指针移动yx设置为空)。

这意味着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签名,以便它采用普通指针。

答案 3 :(得分: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由此临时对象初始化。