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

发布于 2024-10-13 02:35:53 字数 681 浏览 5 评论 0原文

假设我有一个像这样的多态类结构,

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

Lets say I have a polymorphic class Structure like that

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

  }
};

And I've got a third class case1/2 which owns one of those polymorphic object described above. Now I need to pass a pointer to a Base/Deriv object to the constructor of the case1/2 class which takes ownership of this object. Should I pass this object as a smart pointer e.g. auto_ptr to make it clear I'm takin care of this object, or allow raw pointers( case 1 ) to allow a much simpler syntax like

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

叹倦 2024-10-20 02:35:53

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

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 对象在其构造函数中获取其所有权之间抛出异常,则会发生泄漏。

在第二个示例中,如果您没有命名智能指针,则在某些情况下该对象可能会泄漏。值得注意的是,如果某个函数有多个参数,则可能会发生这种情况。

You need to pass a smart pointer and you need to name that smart pointer (e.g., it can't be a temporary):

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.

In your first example, Case1 c(new Deriv);, the object could be leaked if an exception is thrown between when new Deriv is executed and when the Case1 object takes ownership of it in its constructor.

In your second example, where you don't name the smart pointer, the object could be leaked in some circumstances. Notably, this can happen if you have more than one argument to a function.

新雨望断虹 2024-10-20 02:35:53

如果您的类完全拥有传递给它的对象,那么您最好在所有适用的情况下通过使用 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);
    }
};

If your class totally owns the object passed to it, then you are best to make that explicit via the use of auto_ptr in all applicable cases. Having to construct the auto_ptr explicitly is the best case because it enforces that the API user knows that you own that object and reduces the likelyhood of ownership mixups.

If your class has variable ownership, then typically, the way that it's done is to provide a raw pointer and a destruction function.

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);
    }
};
心欲静而疯不止 2024-10-20 02:35:53

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

这样做的原因是,在 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
    }
};

这让事情变得简单,并让客户确切地知道资源将如何管理。

I don't have a source for this being a best practice, but in general if you're going to store a resource in some way, I find it's best to acquire that resource in the same way.

The reason for this is that in C++0x, the copying/moving is done when the argument is given, then you just move it into storage, such as:

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

    std::string s;
};

Or in C++03, if your type can be cheaply default constructed:

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

    std::string s;
};

So for you, I would do:

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

This makes things simple for you, and lets the client know exactly how the resource is going to be managed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文