【问题标题】:How do you assign weak_ptr by passing the "this" keyword?你如何通过传递“this”关键字来分配weak_ptr?
【发布时间】:2019-06-14 13:44:24
【问题描述】:

在我的程序中,组将共享指向主题的指针;和主题将对他们的组有弱指针。我希望 Group 有一个 join() 函数,将 Subject 的弱指针分配给它自己。下面是我尝试过的最小代码。如何修复 join() 函数?

#include <iostream>
#include <string>
#include <memory>

class Party;

class Subject
{
public:
    std::weak_ptr<Party> MyParty;
};

class Party
{
public:
    std::string Name;

    void join(std::shared_ptr<Subject> subject)
    {
        subject->MyParty = std::make_shared<Party>(*this); // <---- PROBLEM
    }
};

int main()
{
    auto& BlueParty = std::make_shared<Party>();
    BlueParty->Name = "Blue Party";

    auto& Jane = std::make_shared<Subject>();

    BlueParty->join(Jane);

    if (auto ptr = Jane->MyParty.lock())
    { 
        std::cout << "I am in " << ptr->Name << std::endl; 
    }

    else { std::cout << "I have no party." << std::endl; }

    return 0;
}

程序打印出“我没有派对”。如果分配成功,应该会打印出“我在蓝方”。

【问题讨论】:

  • 您似乎在寻找std::enable_shared_from_this
  • 问题是Party 并没有意识到它总是由一个shared_ptr 拥有。这不一定是坏事。一种选择是传入要加入的 Party 的 shared_ptr(可以设为静态类函数)。

标签: c++ this weak-ptr


【解决方案1】:

subject-&gt;MyParty = std::make_shared&lt;Party&gt;(*this); 行创建一个新的Party 对象,该对象是*this 的副本,由临时std::shared_ptr 管理。 subject-&gt;MyParty 是从那个临时的 shared_ptr 分配的,但 weak_ptrs 不会保持它们指向的对象处于活动状态。一旦该语句完成,由make_shared 返回的临时shared_ptr 将被销毁并获取它正在管理的Party 对象。 subject-&gt;MyParty 现在不指向任何东西。

解决方法是使用std::enable_shared_from_this:

class Party : public std::enable_shared_from_this<Party>
{
public:
    std::string Name;

    void join(std::shared_ptr<Subject> subject)
    {
        subject->MyParty = shared_from_this();
    }
};

Example

要使用shared_from_this,对象必须std::shared_ptr所有。在这种情况下,标记类的构造函数 private 并使用工厂函数将 shared_ptr 返回到新实例通常是一个好主意,以便该类型的对象不受 shared_ptr 管理不能意外创建:

class Party : public std::enable_shared_from_this<Party>
{
public:
    std::string Name;

    static std::shared_ptr<Party> create()
    {
        return std::shared_ptr<Party>{new Party()};
    }

    void join(std::shared_ptr<Subject> subject)
    {
        subject->MyParty = shared_from_this();
    }
private:
    Party() = default;
    Party(const Party&) = delete;
};

Example

遗憾的是,这使得std::make_shared 更难使用。有关该问题的更多信息,请参阅this question

【讨论】:

  • std::enable_shared_from_this 的危险在于,现在 Party 实例具有自我意识,它们由 shared_ptr 所有。如果在堆栈上创建了一个 Party,但它不是 shared_ptr,并且碰巧以某种方式使用某些东西试图获取 shared_ptr 或 weak_ptr ,这可能是一个问题,它落在 UB 土地上。为了防止这种情况,请使用返回 shared_ptr 的工厂函数,并使用标签键使构造函数不可访问(因为您仍然希望 make_shared 工作)。
  • @Eljay 添加了一个讨论该问题的部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2020-12-06
  • 2010-09-06
  • 1970-01-01
相关资源
最近更新 更多