【问题标题】:Iterator aware objects in std::liststd::list 中的迭代器感知对象
【发布时间】:2020-10-07 15:47:52
【问题描述】:

我有一个对象列表:

std::list<A> objects;

为了触发异步操作,根据某些条件将它们从列表中删除,对象需要知道它们在列表中的位置:

A::A(std::list<A>::iterator it);

向列表添加项目时如何将迭代器传递给构造函数?

objects.emplace(<the iterator to new item>);

后面无法初始化class A的成员迭代器,即使构造函数也可能触发删除操作,所以在构造时需要这个成员。

我想到的可能解决方案(带来额外的复杂性):

1:

objects.emplcae(A(objects.end())); // dummy object
A a{ std::prev(objects.end()) };
std::swap(a, object.back());

2:

objects.emplace();
objects.back().set_iterator(std::prev(objects.end()));
objects.back().run(); // Moved the work from constructor to this function (against RAII)

3:尝试根据this的地址获取迭代器。

【问题讨论】:

  • 您是否考虑过对象不必从列表中删除的替代方案?此外,std::list 本身并不是线程安全的,因此如果对象异步运行,您可能无法安全地删除它自己。
  • 是的,在我当前的实现中,对象不会自行删除,我需要不时触发列表中的删除操作,并且需要遍历所有对象。我的异步模型使用 asio io_context 并且我从单线程运行它,因此所有处理程序都将在单线程中运行。如果我从多个线程运行它,那么我需要处理线程安全。
  • 为什么不能从对象的地址中获取迭代器?我认为列表项是对象后跟两个指向 prev 和 next 的指针,而迭代器是指向该对象的指针。
  • 迭代器可能会也可能不会被实现为指向对象的指针。并且结束指针肯定不会指向列表中的项目。

标签: c++ list iterator


【解决方案1】:

您必须解决一个先有鸡还是先有蛋的问题:A 类希望迭代器在构造对象之前准备好,而迭代器假定某种元素已经构造好了。

解决此问题的一种方法是引入额外的间接级别,例如不存储A 的实例,而是存储指针(智能指针)。另一种方法是使用placementnew:首先在list 中分配一个项目而不构造对象(只分配内存),然后使用提供的迭代器就地构造对象。最简单的解决方案是及时分离A的构造和设置迭代器(A::setIterator(std::list&lt;A&gt;::iterator&amp;)方法)。

我还建议您将其实现为一个工厂方法,该方法采用一个列表(所有成分),并在一个地方完成所有这些容易出错的事情。 Factory 方法应该是 A 的朋友,而构造函数 A::A 应该是私有的。这样可以防止你用其他不正确的方式构造A

【讨论】:

猜你喜欢
  • 2011-10-13
  • 1970-01-01
  • 2013-07-14
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
相关资源
最近更新 更多