如何通过传递 "this" 关键字来分配 weak_ptr?
How do you assign weak_ptr by passing the "this" keyword?
在我的程序中,Groups 将共享指向 Subjects 的指针;并且 Subjects 将有指向其 Groups 的弱指针。我希望 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;
}
程序打印出"I have no party"。如果赋值成功,应该会打印出"I am in Blue Party".
行 subject->MyParty = std::make_shared<Party>(*this);
创建了一个新的 Party
对象,该对象是 *this
的副本并由临时 std::shared_ptr
管理。 subject->MyParty
是从那个临时 shared_ptr
分配的,但是 weak_ptr
不会让它们指向的对象保持活动状态。一旦该语句完成,make_shared
返回的临时 shared_ptr
将被销毁并获取它正在管理的 Party
对象。 subject->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();
}
};
要使用 shared_from_this
,对象 必须 属于 std::shared_ptr
。在这种情况下,将 class 的构造函数标记为 private
并使用一个工厂函数 returns 一个 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;
};
遗憾的是,这使得 std::make_shared
更难使用。有关该问题的更多信息,请参阅 this question.
在我的程序中,Groups 将共享指向 Subjects 的指针;并且 Subjects 将有指向其 Groups 的弱指针。我希望 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;
}
程序打印出"I have no party"。如果赋值成功,应该会打印出"I am in Blue Party".
行 subject->MyParty = std::make_shared<Party>(*this);
创建了一个新的 Party
对象,该对象是 *this
的副本并由临时 std::shared_ptr
管理。 subject->MyParty
是从那个临时 shared_ptr
分配的,但是 weak_ptr
不会让它们指向的对象保持活动状态。一旦该语句完成,make_shared
返回的临时 shared_ptr
将被销毁并获取它正在管理的 Party
对象。 subject->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();
}
};
要使用 shared_from_this
,对象 必须 属于 std::shared_ptr
。在这种情况下,将 class 的构造函数标记为 private
并使用一个工厂函数 returns 一个 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;
};
遗憾的是,这使得 std::make_shared
更难使用。有关该问题的更多信息,请参阅 this question.