将smart_pointer传递给构造函数vs原始指针

时间:2011-01-20 21:10:43

标签: c++ constructor smart-pointers

假设我有类似

的多态类结构
class Base
{
//some implementation
};

class Deriv: public Base
{
//implementation
}

class Case1
{
  boost::scoped_ptr<A> a_ //polymorphic data member owned by C
public:
  Case1(A* a):a_(a)
  {

  }
};
class Case2
{
  boost::scoped_ptr<A> a_ //polymorphic data member owned by C
public:
  Case2(std::auto_ptr<A> a):a_( a.release() )
  {

  }
};

我有一个第三类case1 / 2,它拥有上述多态对象之一。现在我需要将指向Base / Deriv对象的指针传递给case1 / 2类的构造函数,该构造函数接受此对象的所有权。我应该将此对象作为智能指针传递,例如auto_ptr说清楚我正在关注这个对象,或允许原始指针(案例1)允许更简单的语法,如

Case1 c(new Deriv);
//compared to 
Case2 c(std::auto_ptr<Base>(new Deriv));

3 个答案:

答案 0 :(得分:3)

你需要传递一个智能指针,你需要命名该智能指针(例如,它不能是一个临时指针):

std::auto_ptr<Base> p(new Deriv);
Case2 c(p); // this constructor would need to take the `auto_ptr` by reference 
            // so that it can steal ownership.

在您的第一个示例Case1 c(new Deriv);中,如果在执行new DerivCase1对象在其构造函数中获取它的所有权之间抛出异常,则该对象可能会泄露。

在第二个示例中,如果没有为智能指针命名,则在某些情况下可能会泄漏对象。值得注意的是,这可能发生if you have more than one argument to a function

答案 1 :(得分:0)

如果你的类完全拥有传递给它的对象,那么你最好通过在所有适用的情况下使用auto_ptr来明确这一点。必须明确构造auto_ptr是最好的情况,因为它强制API用户知道你拥有该对象并减少了所有权混淆的可能性。

如果你的类具有可变所有权,那么通常,它的方式是提供原始指针和销毁函数。

class best_practices {
    std::function<void(A*)> destructor;
    A* ptr;
public:
    best_practices(A* a, std::function<void(A*)> destructfunc)
        : ptr(a), destructor(destructfunc) {}
    ~best_practices() {
        destructor(ptr);
    }
};

答案 2 :(得分:0)

我没有这个最佳实践的来源,但总的来说,如果您要以某种方式存储资源,我发现最好以相同的方式获取该资源。

原因是在C ++ 0x中,复制/移动是在给出参数时完成的,然后你只需将它移动到存储器中,例如:

struct store_string
{
    store_string(std::string s) : // potentially free, copy if not
    s(std::move(s)) // free
    {}

    std::string s;
};

或者在C ++ 03中,如果您的类型可以廉价地默认构建:

struct store_string
{
    store_string(std::string ss) // make necessary copy
    {
        s.swap(ss); // free
    }

    std::string s;
};

所以对你来说,我会这样做:

class Case2
{
    boost::scoped_ptr<A> a_ //polymorphic data member owned by C
public:
    Case2(boost::scoped_ptr<A>& aa)
    {
        a.swap(aa); // take resource
    }
};

这使您的工作变得简单,并让客户知道如何管理资源。