gpt4 book ai didi

c++ - 如何避免成员回调和 shared_ptr 的循环引用?

转载 作者:行者123 更新时间:2023-11-28 04:07:47 26 4
gpt4 key购买 nike

在我们的代码库中,我们有大量如下情况:

auto f = std::make_shared<Foo>();
auto b = std::make_shared<Bar>();
//void Foo::DoStuff( std::shared_ptr<Foo>, int )
auto func = std::bind( &Foo::DoStuff, f, std::_1 );
b->RegisterFunc( func );

显然,将 shared_ptr 放入存储的回调中通常不是一个好主意,因为它通常会导致 f 永远不会被破坏。通常情况下,您可以只传入一个weak_ptr 并检查它在执行时是否仍然有效。

不幸的是,DoStuff()修改了Foo对象的内部状态,并且是一个成员函数,所以它要求指针是有效避免崩溃。这会导致循环引用,并且需要手动干预,例如调用 Foo::Shutdown() 或其他方法来删除它们。

有没有办法解决存储成员函数回调的循环引用?

注意:出于问题的目的,我要求绑定(bind)函数是非静态成员函数。它在我们的代码中无处不在,无法证明对每个示例进行完全修改是合理的,即使这显然是设计疏忽。

最佳答案

如您所说,您必须使用 weak_ptr 并检查它是否有效。 weak_ptr 可用于创建指向对象的有效指针,因此您仍然可以对从 weak_ptr 获得的指针调用 DoStuff()。我不清楚为什么您认为 weak_ptr 不起作用。

这是您的示例,但现在它显示了使用 weak_ptr 可以避免的潜在循环引用

#include <memory>
#include <functional>
#include <vector>
#include <cassert>

struct Foo {
int x = 0;
using callback_t = std::function<void()>;
std::vector<callback_t> callbacks;

void DoStuff() { x = 1; } //mutate some state
void RegisterFunc(callback_t callback) { callbacks.push_back(std::move(callback)); }
};

using Bar = Foo;

template <class T>
auto wrap_shared_ptr_callback(const std::shared_ptr<T>& p, void(T::*f)()) {
return [p = std::weak_ptr{ p }, f]() {
auto ptr = p.lock();
if (ptr) (*ptr.*f)();
};
}

void create_circular_reference(std::shared_ptr<Foo> f, std::shared_ptr<Bar> b) {
auto f_callback = wrap_shared_ptr_callback(f, &Foo::DoStuff);
b->RegisterFunc( f_callback );
auto b_callback = wrap_shared_ptr_callback(b, &Bar::DoStuff);
f->RegisterFunc( b_callback );

// test callbacks
b->callbacks.front()();
f->callbacks.front()();
}

int main() {
auto f = std::make_shared<Foo>();
auto b = std::make_shared<Bar>();

// keep weak ptrs so we can check they've been destroyed correctly
auto f_w = std::weak_ptr{ f };
auto b_w = std::weak_ptr{ b };

create_circular_reference(std::move(f), std::move(b));

assert(f_w.expired());
assert(b_w.expired());
}

关于c++ - 如何避免成员回调和 shared_ptr 的循环引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58403208/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com