C++ 如何将manager的引用传递给handler对象?
我想做的是编写一个小型的管理器/处理程序类。经理分发和管理句柄。例如,这样的句柄可以是一个简单的文件句柄 如果使用者希望获得已存在的句柄,则管理器只需返回一个共享的\u ptr。如果句柄不存在,管理器将创建一个新句柄,然后返回共享的\u ptr 在管理器内部,这些共享的ptr存储在一个简单的STL映射中。 如果上次分配的共享_ptr被删除,我希望我的管理器删除相关的map元素,以便处理程序对象自动被销毁 这听起来有点像垃圾收集(例如,worker线程,它检查指针的使用计数),但我相信它可以做得更优雅 如何将manager实例的引用传递给handler对象?(例如,向新处理程序的构造函数传递一个唯一的\u ptr(this)C++ 如何将manager的引用传递给handler对象?,c++,c++11,memory-management,C++,C++11,Memory Management,我想做的是编写一个小型的管理器/处理程序类。经理分发和管理句柄。例如,这样的句柄可以是一个简单的文件句柄 如果使用者希望获得已存在的句柄,则管理器只需返回一个共享的\u ptr。如果句柄不存在,管理器将创建一个新句柄,然后返回共享的\u ptr 在管理器内部,这些共享的ptr存储在一个简单的STL映射中。 如果上次分配的共享_ptr被删除,我希望我的管理器删除相关的map元素,以便处理程序对象自动被销毁 这听起来有点像垃圾收集(例如,worker线程,它检查指针的使用计数),但我相信它可以做得更
#包括
#包括
#包括
使用名称空间std;
/*
*简单的处理程序类,实际上什么都不做。
*这可能是例如Filehandler类或类似的东西
*/
类处理程序{
私人:
int i;
公众:
Handler(inti):i(i){}
~Handler(){}
//说你是谁。
作废打印(作废){cout将std::weak_ptr
对象存储在映射中;它们不保留所有权,因此当最后一个std::shared_ptr
对象离开时,资源将被销毁。但它们会跟踪是否有剩余的std::shared_ptr
对象指向原始对象,因此将它们放在映射中稍后您将检查是否仍有资源。您可能希望在管理器中保留非所有权指针以跟踪现有句柄,并通过自定义删除器放弃所有权共享的\u ptr
。自定义删除器将确保在对象最终被删除时删除管理器中相应的观察指针它被摧毁了
我调用了这个模式跟踪工厂,下面是它的工作原理。给定一个对象
类(在您的情况下是处理程序
):
然后,程序的其余部分将通过对象工厂
:如果对象具有所需特征(此处为id
成员),获得对象的共享ptr
s已创建,将返回到它的共享\u ptr
,而不实例化新对象。下面是一些测试功能的代码:
#include <iostream>
int main()
{
tracking_factory f;
auto print_object_count = [&f] ()
{
std::cout << "Number of objects: " << f.count_instances() << std::endl;
};
print_object_count();
auto p1 = f.get_object(42);
print_object_count();
{
auto p2 = f.get_object(42);
print_object_count();
p1 = f.get_object(0);
print_object_count();
}
print_object_count();
p1.reset();
print_object_count();
}
#包括
int main()
{
跟踪f工厂;
自动打印对象计数=[&f]()
{
std::非常感谢!但是,我会在我的映射中使用“死”过期的弱指针。这不是致命的,因为我可以识别它们。有没有一种聪明的方法可以在处理程序类中存储管理器类的引用?这样,每当处理程序被销毁时,我就可以在管理器中强制调用收集垃圾函数。@rralf:You不需要垃圾收集。如果你想避免过期的弱指针,你可以使用一个自定义的删除器在销毁时删除它们。我已经在我的答案中描述了这一点。这正是我正在寻找的。非常感谢!Rralf:欢迎你:如果这解决了你的问题,请考虑将答案标记为接受。(或者你可能更喜欢的任何其他答案)。嗯,valgrind告诉我,你的示例在某个地方泄漏,但我不知道它到底泄漏在哪里……我认为你的自定义删除程序忽略了它的名称。@rralf:我发现了问题(非常尴尬,我忘了在删除程序中调用delete
)并且还修改了原始版本,使用地图而不是矢量-这简化了很多事情。你能检查一下这对你来说是否合适吗?
class object
{
public:
size_t get_id() const
{
return _id;
}
private:
friend class tracking_factory;
object(size_t id) : _id(id) { }
size_t _id = static_cast<size_t>(-1);
};
class tracking_factory
{
public:
std::shared_ptr<object> get_object(size_t id,
bool createIfNotFound = true)
{
auto i = std::find_if(
begin(_objects),
end(_objects),
[id] (std::pair<size_t const, std::weak_ptr<object>> const& p)
-> bool
{
return (p.first == id);
});
if (i != end(_objects))
{
return i->second.lock();
}
else if (createIfNotFound)
{
return make_object(id);
}
else
{
return std::shared_ptr<object>();
}
}
size_t count_instances() const
{
return _objects.size();
}
private:
std::shared_ptr<object> make_object(size_t id)
{
std::shared_ptr<object> sp(
new object(id),
[this, id] (object* p)
{
_objects.erase(id);
delete p;
});
_objects[id] = sp;
return sp;
}
std::map<size_t, std::weak_ptr<object>> _objects;
};
#include <iostream>
int main()
{
tracking_factory f;
auto print_object_count = [&f] ()
{
std::cout << "Number of objects: " << f.count_instances() << std::endl;
};
print_object_count();
auto p1 = f.get_object(42);
print_object_count();
{
auto p2 = f.get_object(42);
print_object_count();
p1 = f.get_object(0);
print_object_count();
}
print_object_count();
p1.reset();
print_object_count();
}