使用std :: auto_ptr数据成员是否会调用UB?

时间:2010-11-23 19:41:50

标签: c++ standards-compliance auto-ptr

作为Class containing auto_ptr stored in vector的后续内容,我相信没有明确的结论是,使用auto_ptr成员作为容器元素的类是可以的,只要两者复制构造和复制赋值是用户定义的(以便不调用auto_ptr的复制构造函数和复制赋值。是否存在违反标准库要求的任何

请告诉我以下是否有任何问题,因为我想以惯用方式开始这样做:

#include <memory>
#include <algorithm>

class Y { /* ... */ };
class Z : public Y { /* ... */ };

class X {
    public:
        X() : ap(new Z()) {}
        X(const X& other) : ap(other.ap->clone()) {}
        X& operator=(X other) { swap(other); return *this; } // any problem with swap?
        void swap(X& other) { std::swap(ap, other.ap); }
        // note no destructor necessary
    private:
        std::auto_ptr<Y> ap; // Y provides clone()
};

请注意,有一件事我已经意识到,使用这种方法,Y的类定义必须在X定义的范围内(而不是仅仅在向前声明时)使用原始“指向Y的指针”。这是因为当auto_ptr被实例化时,它的析构函数必须在Y上调用delete,因此Y不能是不完整的类型。我想在类X管理多个资源(有几个auto_ptr成员)的情况下,必须权衡RAII的值。有什么想法吗?

我认为这种技术总体来说很棒,为类可能必须构造/破坏/复制潜在的多个资源(单一责任主体)的类消除了许多棘手的代码。我只是想知道auto_ptr是否符合此目的,或者由于某些微妙的语言/标准库要求而无法在此处工作。

请注意我知道其他类型的智能指针,但我正在实现库接口,我不想对我的客户端强加Boost或TR1的任何要求。任何有关使用auto_ptr的讲座都将被低估!

3 个答案:

答案 0 :(得分:1)

我认为您已在std::auto_ptr之上实施了 克隆智能指针 。我不确定这是否值得麻烦,因为你在愚蠢的指针之上实现一个并不是很远。

但据我所知,这里没有错误。 (当然,这样说会让我在发布此帖后5分钟指出一个明显的缺陷......)

答案 1 :(得分:1)

当析构函数超出范围时使用auto_ptr 会导致未定义的行为。 MSVC警告它。海湾合作委员会没有。

您可以使其工作,但前提是未将析构函数定义为内联函数。

unique_ptr和scoped_ptr解决了这个问题。至少在那些情况下你无法编写未定义的代码。

答案 2 :(得分:-1)

你真的想做什么? 如果您只想在容器中放置一堆对象,似乎有很多不必要的工作。创建临时对象并让容器中的对象接管所有权在我的想法中不是问题

operator =()对我没有意义,它不是=它是交换。

X a,b;
a=b
assert(a==b) // fail!

您的认识不正确

  

请注意,我意识到的一件事是   用这种方法,Y的班级   定义必须在X的范围内   定义(而不仅仅是   当一个“原始”指针时向前声明   使用Y)。这是因为什么时候   auto_ptr是实例化的,它的   析构函数必须在Y上调用delete,   所以Y不能是一个不完整的类型。

如果为X定义析构函数并在CPP文件中实现,则可以合法地执行

class Y;
class X{
  virtual ~X();
  std::auto_ptr<Y> ap; 
};

class Y{};
~X(){}