C++ std::shared_ptr 这个

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11711034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:27:00  来源:igfitidea点击:

std::shared_ptr of this

c++thisshared-ptrthis-pointer

提问by Icarus

I am currently trying to learn how to use smart pointers. However while doing some experiments I discovered the following situation for which I could not find a satifying solution:

我目前正在尝试学习如何使用智能指针。然而,在做一些实验时,我发现了以下情况,我找不到令人满意的解决方案:

Imagine you have an object of class A being parent of an object of class B (the child), but both should know each other:

假设您有一个 A 类对象是 B 类对象(子对象)的父对象,但两者都应该相互认识:

class A;
class B;

class A
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children->push_back(child);

        // How to do pass the pointer correctly?
        // child->setParent(this);  // wrong
        //                  ^^^^
    }

private:        
    std::list<std::shared_ptr<B>> children;
};

class B
{
public:
    setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    };

private:
    std::shared_ptr<A> parent;
};

The question is how can an object of class A pass a std::shared_ptrof itself (this) to its child?

问题是类 A 的对象如何将其std::shared_ptr自身 ( this) 的a 传递给其子对象?

There are solutions for Boost shared pointers (Getting a boost::shared_ptrfor this), but how to handle this using the std::smart pointers?

有针对 Boost 共享指针的解决方案(获取boost::shared_ptrforthis),但是如何使用std::智能指针处理这个问题?

回答by yuri kilochek

There is std::enable_shared_from_thisjust for this purpose. You inherit from it and you can call .shared_from_this()from inside the class. Also, you are creating circular dependencies here that can lead to resource leaks. That can be resolved with the use of std::weak_ptr. So your code might look like this (assuming children rely on existence of parent and not the other way around):

std::enable_shared_from_this只是为了这个目的。你从它继承,你可以.shared_from_this()从类内部调用。此外,您正在此处创建可能导致资源泄漏的循环依赖项。这可以通过使用std::weak_ptr. 所以你的代码可能看起来像这样(假设孩子依赖父母的存在而不是相反):

class A;
class B;

class A
    : public std::enable_shared_from_this<A>
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children.push_back(child);

        // like this
        child->setParent(shared_from_this());  // ok
        //               ^^^^^^^^^^^^^^^^^^
    }

private:     
    // note weak_ptr   
    std::list<std::weak_ptr<B>> children;
    //             ^^^^^^^^
};

class B
{
public:
    void setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    }

private:
    std::shared_ptr<A> parent;
};

Note however, that calling .shared_from_this()requires that thisis owned by std::shared_ptrat the point of call. This means that you cannot create such object on stack anymore, and generallycannot call .shared_from_this()from within a constructor or destructor.

但是请注意,调用.shared_from_this()需要在调用点this拥有它std::shared_ptr。这意味着您不能再在堆栈上创建这样的对象,并且通常不能.shared_from_this()从构造函数或析构函数中调用。

回答by ?imon Tóth

You have several problems in you design, that seem to stem from you misunderstanding of smart pointers.

您在设计中遇到了几个问题,这似乎源于您对智能指针的误解。

Smart pointers are used to declare ownership. You are breaking this by declaring that both the parents owns all children, but also that each child own it's parent. Both can't be true.

智能指针用于声明所有权。您通过声明父母双方拥有所有孩子,而且每个孩子都拥有它的父母来打破这一点。两者都不可能是真的。

Also, you are returning a weak pointer in getChild(). By doing so, you are declaring that the caller shouldn't care about the ownership. Now this can be very limiting, but also by doing so, you must make sure that the child in question won't get destroyed while any weak pointers are still held, if you would use a smart pointer, it would get sorted out by itself.

此外,您正在返回一个弱指针getChild()。通过这样做,您声明调用者不应该关心所有权。现在这可能是非常有限的,但通过这样做,您必须确保在仍然持有任何弱指针时不会破坏有问题的孩子,如果您使用智能指针,它会自行解决.

And the final thing. Usually, when you are accepting new entities, you should usually accept raw pointers. Smart pointer can have their own meaning for swapping children between parents, but for general usage, you should accept raw pointers.

最后的事情。通常,当您接受新实体时,您通常应该接受原始指针。对于在父母之间交换孩子,智能指针可以有自己的含义,但对于一般用法,您应该接受原始指针。