【问题标题】:stl : map of vectors - begin() addressstl : 向量图 - begin() 地址
【发布时间】:2015-09-16 08:57:29
【问题描述】:

我已经奋斗了几个小时来理解为什么如果我指向 vector.begin() 本身或地图中的 second.begin() 成员,地图中矢量的 begin() 不会返回相同的地址。

让我解释一下:

我有一个类,其中包含一个映射,其键是 int,其内容是 int 的向量。我必须浏览地图并在内存中保留我“之前”的位置,所以我还有另一个迭代器地图(第一张地图)。

所以,我想得到类似的东西:

  • 地图1:>
  • 地图2:>
  • 地图3:>

为了简单起见,在我的代码中,T_IPC_CommandId 只是 int 的枚举。

我有一个名为Add(int TopCommand, int Command) 的方法,它填充/创建命令向量的映射。比如创建map3,我会编码:

Add(1,3), Add(1,1)

我有一个名为GetNext(int Command) 的方法,它在Command 指向的映射中返回下一个int。例如在map2 中,调用Get(8) 将返回6,下一次调用将返回9,然后是130 用于下一次调用。

为了知道我会返回哪个int,我需要跟踪每张地图,下一个int 会返回什么。所以,我使用了IPC_CommandId_Pointer,它是一个映射,它的键是命令本身,并将迭代器保存在我在映射中的位置。这就是问题所在:

在每次Add() 调用时,我都会将此IPC_CommandId_Pointer 初始化为主地图的开头。像这样:

        void T_ListOfCommand::Add(T_IPC_CommandId   Top_CommandId, T_IPC_CommandId IPC_CommandId)
    {
        T_IPC_CommandId_Vec_Iter Vec_Iter;
        T_IPC_CommandId_Vec      Vec;

        if ((IPC_CommandId_Map.find(Top_CommandId)) == IPC_CommandId_Map.end())
        {

            IPC_CommandId_Map[Top_CommandId].clear();
        }
        IPC_CommandId_Map[Top_CommandId].push_back(IPC_CommandId);

        // Repeated at each add, but don't care ...
        Vec_Iter = IPC_CommandId_Map[Top_CommandId].begin();
        IPC_CommandId_Pointer[Top_CommandId] = Vec_Iter;
    }

我遇到的问题是,在每个IPC_CommandId_Map[Top_CommandId].push_back(IPC_CommandId)IPC_CommandId_Map[Top_CommandId].begin() 不会返回相同的地址。

现在,当更换:

Vec_Iter = IPC_CommandId_Map[Top_CommandId].begin();
IPC_CommandId_Pointer[Top_CommandId] = Vec_Iter;

与:

Vec = IPC_CommandId_Map[Top_CommandId];
IPC_CommandId_Pointer[Top_CommandId] = Vec.begin();

这很好用。

我想在地图中使用begin() 或取消引用向量时指向同一个位置,不是吗?嗯,好像没有。

如果有人能解释我的区别,那就太好了。

【问题讨论】:

  • 您能否将问题缩小到相关代码?
  • 代码Vec = IPC_CommandId_Map[Top_CommandId];复制映射元素到变量Vec

标签: c++ dictionary vector stl


【解决方案1】:

vector::begin()不保证每次都返回相同的地址!

如果std::vector::push_back() 导致向量数据的重新分配(因为它的数据必须是连续的),那么begin() 返回的迭代器(地址)将会不同。

并且(如注释中所述的The Paramagnetic Croissant)代码Vec = IPC_CommandId_Map[Top_CommandId]; 将映射的元素复制到变量Vec。

【讨论】:

  • push_back() 导致重新分配的事实不是我所知道的。谢谢大家的澄清。
【解决方案2】:

(词汇检查:您没有取消引用任何内容,尤其是向量。)

Vec_Iter = IPC_CommandId_Map[Top_CommandId].begin();

是地图中向量的迭代器。
重新分配向量时,它变得无效。
每次重新分配向量时,您都会得到不同的 begin() 值。
将此迭代器存储在对 push_back 或任何其他可能使迭代器无效的调用之间是一个坏主意。

Vec = IPC_CommandId_Map[Top_CommandId];
IPC_CommandId_Pointer[Top_CommandId] = Vec.begin();

是本地副本Vec的迭代器。
函数一返回就失效了。
将此迭代器存储在Vec 的生命周期之外任何地方 是个坏主意。

总的来说,迭代器应该被认为是瞬态的,并且只能在尽可能小的范围内使用。

更强大的解决方案是为向量存储“当前索引”而不是迭代器。

【讨论】:

  • 非常感谢您的回答;事实上,这两种方式都是“坏主意”,现在,我明白为什么了。但即使第二种解决方案“有点作用”,是否意味着它在生命周期内得不到保证?我绝对同意存储“当前索引”会更好;但是存储迭代器本身是一件“很好”的事情。嗯,当时。
猜你喜欢
  • 2015-11-13
  • 2022-01-15
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多