使用 std::vector 作为 std::map 的键在未找到和使用 reserve() 时不会返回 end()

Using std::vector as a key for std::map does not return end() when not found and using reserve()

本文关键字:std reserve end 返回 map 作为 vector 使用      更新时间:2023-10-16

我正在一个程序中使用 c++ STL Map 和 Vector 类,其中我有一个将向量作为指向整数的键的映射。通常,在映射中搜索值时,如果未找到该值,myMap.find() 将返回 myMap.end()。

当我尝试使用 myVector.reserve(int) 在我的向量中预先分配空间(以防止在使用它们时不断调整大小)时,我的麻烦就出现了。出于某种原因,当我搜索的向量分配了空间时,在我的地图中搜索我知道不存在的向量将不会返回 myMap.end(),无论我是否实际填充了向量(示例 1)。

但是,当矢量不在地图中时,简单地将对象插入到我要搜索的向量中会给我正确的 myMap.end() 位置(示例 2)。

示例 1:

#include <map>
#include <vector>
#include <iostream>
using namespace std;
int main(){
 vector<int> v, v1;
 v.reserve(1);
 v1.reserve(1);
 v[0] = 1;
 v1[0] = 2;
 map<vector <int>, int> m;
 m.insert(make_pair(v, 0));
 cout << int(m.find(v1) == m.end());
}

返回 0

示例 2:

#include <map>
#include <vector>
#include <iostream>
using namespace std;
int main(){
 vector<int> v, v1;
 v.reserve(1);
 v[0] = 1;
 v1.push_back(5);
 map<vector <int>, int> m;
 m.insert(make_pair(v, 0));
 cout << int(m.find(v1) == m.end());
}

返回 1

我希望能够在我的矢量中保留一定数量的空间,但似乎让地图按所示工作的唯一方法是动态插入元素并动态调整矢量大小。这是对的吗?有什么解决方法吗?任何人都可以为这种(明显的)aberrant行为提供解释吗?

首先,这段代码并没有像你认为的那样。 reserve() 不会调整大小()。

vector<int> v;
v.reserve(100);
v[0] = 1;  //undefined
cout << v.size(); //prints 0

再编辑一下:我意识到这实际上是"预期"行为,因为在第一种情况下,v 和 v1 都是空向量,因为保留不会影响 ==、<= 等的语义。 一旦你明白储备实际上什么也没做,只是把段错误变成令人困惑的行为,这应该是有道理的。 我建议在你证明它会产生性能差异(过早优化)之前,不要使用储备。

我对 <= 和 => 以及地图的描述你可能不需要这里,但把它留作参考,因为它可能会影响你在这个问题上的工作。

其次,地图不在乎事物是否==。 他们关心事物是否在两个方向上都<=——这个词是"等价的"。 例如

Foo foo1(1);
Foo foo2(2);
map<Foo, int> m;
m.insert(makepair(foo1, 1));
m.find(foo2) == m.end(); //will be true iff foo1 <= foo2 && foo2 <= foo1
//even if foo1 != foo2 or !(foo1 == foo2)
因此,如果在某个类 Foo, if(foo1 <= foo2 && foo2 <= foo1) 则 somemap.insert(makepair(foo1

, 1)); somemap.find(foo2) 将找到 foo1,即使 foo1 != foo2 或 !(foo1 == foo2)。

其次,您在向量的 <= 运算符是什么? 它不是测试具有相同的大小并且逐点==。 我认为每个向量都是"等价的",这意味着两个方向的 <=,到空向量,但我不确定 - 无论如何都要考虑这种行为,因为这就是问题所在。