【发布时间】:2011-02-24 14:46:38
【问题描述】:
我在多线程应用程序中有一个映射,将一个名为 uuid 的类映射到指针。 我想知道插入操作是否成功失败。
例如
_mymap.insert(hint, MyMap::value_type(entry.uuid, itemptr));
如果失败会抛出异常还是什么?
【问题讨论】:
-
@Armen,试过了。我找不到任何显示它的例子。所有示例都假设插入成功。
我在多线程应用程序中有一个映射,将一个名为 uuid 的类映射到指针。 我想知道插入操作是否成功失败。
例如
_mymap.insert(hint, MyMap::value_type(entry.uuid, itemptr));
如果失败会抛出异常还是什么?
【问题讨论】:
实际上,带有提示参数的插入方法不会返回插入是否成功。检查插入是否实际发生的一种方法是在插入前后检查地图的大小。如果相同,则插入失败(即密钥已经存在)。我知道这听起来很难看,但这是我能想到的最有效的方法。事实上,我认为没有令人信服的理由表明带有提示的插入不应该像常规的非提示插入那样返回一对(包括布尔值)。但一旦在旧标准中指定,就很难更改,因为这是一个重大更改,C++ 社区对此大多不满。
... 返回一个对,其成员 pair::first 设置为一个迭代器,该迭代器指向新插入的元素或映射中已经具有相同值的元素。如果插入了新元素,则该对中的 pair::second 元素设置为 true,如果存在具有相同值的元素,则设置为 false。
该链接还包含一个示例
例如:
if(mp.insert(make_pair(key, value)).second == false)
{
cout << "Insertion failed. Key was present"
}
【讨论】:
insert 的提示版本返回 iterator 而不是 pair 的原因,Nicolai M. Josuttis 在他的“C++ 标准库”(第一和第二版)中第二个版本),通过这样说你有一个insert函数,它对所有容器类型具有相同的接口在STL中定义(vector,deque,list 、set、multiset、map、multimap)。
insert_or_assign(c++17 标准),其返回的布尔值(如果使用不带提示的版本)区分插入大小写 (true) 和赋值情况(假)。见reference
typedef std::map<std::string, int> map;
map m;
std::pair<map::iterator,bool> result = m.insert(std::make_pair("hi", 42));
result.second 包含你想要的内容
【讨论】:
第一个插入成员函数 返回一对其 bool 组件 如果进行了插入,则返回 true 如果地图已经包含,则为 false 其键具有等价的元素 排序中的值,并且其 迭代器组件返回地址 插入新元素的位置或 元素所在的位置。
访问一个迭代器组件 该成员返回的对 pr 函数,使用 pr.first,并 取消引用它,使用 *(pr.first)。到 访问一对 pr 的 bool 组件 此成员函数返回,使用 pr.second.
第二个插入成员函数, 提示版本,返回一个迭代器 指向新的位置 元素已插入到地图中。
来源:http://msdn.microsoft.com/en-us/library/81ac0zkz(v=vs.80).aspx
【讨论】:
这取决于你所说的失败或成功。
std::map::insert 在插入新元素时成功,否则返回一个指向已存在元素的迭代器。
如果没有足够的内存来插入新元素,std::map::insert 将失败并抛出 std::bad_alloc。
【讨论】:
是的,它会抛出 STL 中使用的异常之一,例如当内存不足时。这是失败的情况。
或者您是否也想知道该元素是否已包含在实例中?
【讨论】:
在插入提示后,还可以知道在地图中是否插入或找到了一对(更快)。
使用提示方法插入另一对相同的第一对,以及您确定不在地图中的第二对(如 -1 表示正第二个整数的地图)。如果返回的迭代器有这个不可能的值,它是新插入的,如果不是,它是在map中找到的。然后可以更改返回的迭代器。
示例:在 map
int main (int argc, char* argv []) {
std::pair<int, int> tmp [3] = {
std::pair<int, int> (0, 1),
std::pair<int, int> (2, 3),
std::pair<int, int> (4, 5)
};
std::map<int, int> m ((std::pair<int, int>*) tmp, (std::pair<int, int>*) &tmp [3]);
std::cout << "initial map == ";
std::for_each (m.begin (), m.end (), [] (const std::pair<int, int>& p) {
std::cout << p.first << "->" << p.second << " ";
});
std::cout << std::endl;
std::cout << std::endl;
{
//insertion of a pair of first already in map
std::cout << "insertion of pair 1 == std::pair<int, int> (2, 4) from second iterator" << std::endl;
std::map<int, int>::iterator ihint (m.begin ()), k (ihint); ++ihint;
std::pair<int, int> pfoo (2, -1);
k = m.insert (ihint, pfoo);
if (k->second == -1) {
std::cout << "\tthe pair was inserted" << std::endl;
k->second = 4;
}
else {
std::cout << "\ta pair with such a first was in the map" << std::endl;
}
}
std::cout << "m after insertion of pair 1 == ";
std::for_each (m.begin (), m.end (), [] (const std::pair<int, int>& p) {
std::cout << p.first << "->" << p.second << " ";
});
std::cout << std::endl;
std::cout << std::endl;
{
//insertion of a pair of first not in map
std::cout << "insertion of pair 2 == std::pair<int, int> (6, 5) from third iterator" << std::endl;
std::map<int, int>::iterator ihint (m.begin ()), k (ihint); ++ihint; ++ihint;
std::pair<int, int> pfoo (6, -1);
k = m.insert (ihint, pfoo);
if (k->second == -1) {
std::cout << "\tthe pair was inserted" << std::endl;
k->second = 5;
}
else {
std::cout << "\ta pair with such a first in the map" << std::endl;
}
}
std::cout << "m after insertion of pair 2 == ";
std::for_each (m.begin (), m.end (), [] (const std::pair<int, int>& p) {
std::cout << p.first << "->" << p.second << " ";
});
std::cout << std::endl;
}
输出: 初始映射 == 0->1 2->3 4->5
从第二个迭代器插入对 1 == std::pair
地图上有一对这样的第一对
插入对后的m == 0->1 2->3 4->5
从第三个迭代器插入对 2 == std::pair
这对已插入
插入pair后的m == 0->1 2->3 4->5 6->5
【讨论】: