2011-01-20 68 views
1

可以说我有一个多态类结构类似的通smart_pointer来构造VS原始指针

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()) 
    { 

    } 
}; 

而且我有一个三等功案例1/2拥有上述这些多态对象之一。现在我需要将一个指向Base/Deriv对象的指针传递给case1/2类的构造函数,该类取得了该对象的所有权。我是否应该将此对象作为智能指针传递给auto_ptr的,使之清楚,我要拿回这个对象的照顾,或允许原始指针(案例1)允许一个更简单的语法像

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

回答

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 Deriv被执行,当Case1对象占用的所有权之间抛出的对象可能会被泄露它在它的构造函数中。

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

+0

你的意思是在中间发生的完全零代码?我也不明白为什么它不能是暂时的。 – Puppy 2011-01-20 21:16:23

+0

@DeadMG:零码在哪里?如果`Case1`构造函数在将原始指针参数分配给智能指针之前做了任何可能会引发异常的事件,则该对象将被泄漏。我已经添加了一个关于Herb Sutter的GOTW文章的链接。如果构造函数只有一个参数,这不是问题,但即便如此,大多数良好的编码风格(包括Boost指南)都建议为此指定所有智能指针。 – 2011-01-20 21:17:04

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); 
    } 
}; 
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 
    } 
}; 

这使得日这对你来说很简单,并让客户确切知道资源将如何管理。