我正在尝试在我的代码中使用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);
似乎课程被毁了,但我不明白为什么......
答案 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
中的指针移动到y
(x
设置为空)。
这意味着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由此临时对象初始化。