钩住std::list中的对象.指针或迭代器

Hook on object in std::list. Pointer or iterator?

本文关键字:指针 对象 迭代器 std list 钩住      更新时间:2023-10-16

我寻找了相同类型的问题,但没有找到问题的答案(存在问题):我应该选择什么类型的钩子来控制列表中的对象?我在指针和迭代器之间摇摆不定。

容器在开始时已填充,之后不应调整大小。钩子是我用来根据用户的意愿在对象之间切换的方式,并且只操作算法中的一个变量。

在所有情况下,我都必须通过迭代器来找到要挂接的正确对象。但是哪一个是最佳实践/用途?

// 10 object list
std::list <Object> List(10);
std::list <Object>::iterator it = List.begin();
Object *pt = NULL;
// Select the 3rd object
advance(it, 3);
pt = &(*it);
// Access to object member...
it->member;
pt->member;

与迭代器相反,指针不允许访问邻居,但可能不安全。最好的练习是什么?

这取决于你想用"钩子"做什么。如果您使用迭代器,它可以用作移动的起点在列表中向前或向后。如果你使用指针,你可以也指向列表之外的对象。最后,它取决于您期望代码如何发展。

将指针或迭代器存储到容器中是非常危险的,因为当您使用它们时(即,如果容器或数据发生更改),您可能会发现它们是无效的。

一种更通用、更稳健的方法可能是使用地图而不是列表。每个值都由一个密钥(你喜欢的任何类型)标识,你可以很容易地存储密钥,并在使用它们之前检查它们是否有效,例如:

std::map<int, std::string> data;
// Add stuff to the map
data[5] = "blah";
data[27] = "foo";
// Check if a key exists
if (data.find(31) == data.end()) {
    // Key 31 does NOT exist
} else {
    // Key 31 DOES exist
}

不过需要注意的一点是,映射是按键值排序的。这意味着,如果元素的顺序很重要,那么你需要仔细选择你的键。

在大多数情况下使用引用:

Object& ref = *it;
ref.member

它的行为就像一个指针(所以可以随意传递函数),但不能对它进行指针运算(ref++实际上会调用Object上的operator++())。此外,您不能从null初始化它(当您尝试创建引用时,将报告为错误)。

需要记住的一点是,您仍然需要将对象放置在某个位置。如果说某个函数从列表中删除了Object,那么就不应该再使用ref了。