我如何知道 std::map 插入成功还是失败?

发布于 2024-10-19 04:53:44 字数 183 浏览 2 评论 0原文

我在多线程应用程序中有一个映射,将名为 uuid 的类映射到指针。 我想知道插入操作是否成功或失败。

例如,

_mymap.insert(hint, MyMap::value_type(entry.uuid, itemptr));

如果失败,它会抛出异常或其他异常吗?

I have a map in a multithreaded app mapping a class called uuid to pointer.
What I want to know if an insert operation succeeded for failed.

e.g.

_mymap.insert(hint, MyMap::value_type(entry.uuid, itemptr));

Does it throw an exception or something if it fails?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

沉鱼一梦 2024-10-26 04:53:44

事实上,带有提示参数的插入方法不会返回插入是否成功。检查插入是否实际发生的一种方法是检查插入前后地图的大小。如果相同,则插入失败(即密钥已经存在)。我知道这听起来很丑陋,但这是我能想到的最有效的方法。事实上,我认为没有令人信服的理由表明带有提示的插入不应像常规的非提示插入那样返回一对(包括布尔值)。但是,一旦在较旧的标准中指定了它,就很难更改,因为这是一个重大更改,而 C++ 社区大多对此表示不满。

原始(错误)答案

查看此链接

...返回一对,其中它的成员pair::first设置为一个迭代器,该迭代器指向新插入的元素或指向映射中已具有相同值的元素。如果插入了新元素,则对中的 pair::second 元素设置为 true;如果存在具有相同值的元素,则设置为 false。

该链接还包含一个示例

例如:

if(mp.insert(make_pair(key, value)).second == false)
{
   cout << "Insertion failed. Key was present"
}

In fact the insert method which takes a hint parameter does not return whether the insert succeeded or not. One way to check if insert actually happened would be to check the size of the map before and after insertion. If it is the same, then insert has failed (i.e. the key was already present). I know it sounds ugly, but that's the most efficient way I could come up with. In fact I believe that there is no compelling reason that the insert with a hint should not return a pair (including the bool) just like the regular non-hint insert does. But once it has been specified in an older standard, it is very hard to change, since it is a breaking change, which the C++ community mostly resents.

Original (wrong) answer

See this link

... returns a pair, with its member pair::first set to an iterator pointing to either the newly inserted element or to the element that already had its same value in the map. The pair::second element in the pair is set to true if a new element was inserted or false if an element with the same value existed.

The link also contains an example

For example:

if(mp.insert(make_pair(key, value)).second == false)
{
   cout << "Insertion failed. Key was present"
}
永言不败 2024-10-26 04:53:44
typedef std::map<std::string, int> map;
map m;
std::pair<map::iterator,bool> result = m.insert(std::make_pair("hi", 42));

result.second 包含你想要的内容

typedef std::map<std::string, int> map;
map m;
std::pair<map::iterator,bool> result = m.insert(std::make_pair("hi", 42));

result.second contains what you want

魄砕の薆 2024-10-26 04:53:44

这取决于你所说的失败或成功是什么意思。

std::map::insert 当插入新元素时成功,否则返回一个指向已存在元素的迭代器。

如果没有足够的内存来插入新元素,std::map::insert 将失败并抛出 std::bad_alloc

It depends what you mean by failed or succeeded.

std::map::insert succeeds when it inserts the new element, otherwise it returns an iterator to an already existing element.

std::map::insert fails if there is not enough memory to insert a new element and throws std::bad_alloc.

夜还是长夜 2024-10-26 04:53:44

第一个插入成员函数
返回一个对,其 bool 组件
如果进行了插入则返回 true
如果地图已包含则为 false
其键具有等价元素的元素
排序中的值,以及其
迭代器组件返回地址
插入新元素的位置或
元素已经位于的位置。

访问 a 的迭代器组件
该成员返回的对 pr
函数,使用 pr.first,并且
取消引用它,使用 *(pr.first)。到
访问对 pr 的 bool 组件
由该成员函数返回,使用
pr.第二。

第二个插入成员函数,
提示版本,返回一个迭代器
指向新的位置
元素已插入到地图中。

来源:http://msdn.microsoft.com/ en-us/library/81ac0zkz(v=vs.80).aspx

The first insert member function
returns a pair whose bool component
returns true if an insertion was made
and false if the map already contained
an element whose key had an equivalent
value in the ordering, and whose
iterator component returns the address
where a new element was inserted or
where the element was already located.

To access the iterator component of a
pair pr returned by this member
function, use pr.first, and to
dereference it, use *(pr.first). To
access the bool component of a pair pr
returned by this member function, use
pr.second.

The second insert member function, the
hint version, returns an iterator that
points to the position where the new
element was inserted into the map.

Source: http://msdn.microsoft.com/en-us/library/81ac0zkz(v=vs.80).aspx

一杆小烟枪 2024-10-26 04:53:44

是的,它会抛出 STL 中使用的异常之一,例如内存不足时。那是在失败的情况下。

或者您是否也有兴趣了解该元素是否已包含在实例中?

Yes, it would throw one of the exceptions used in the STL, e.g. when out of memory. That is in case of failure.

Or were you also interested in knowing whether the element was already contained in the instance?

我偏爱纯白色 2024-10-26 04:53:44

如果 insert() 尝试插入但失败,则抛出 std::bad_alloc ;如果它选择不插入,因为具有该键的值已经存在,那么它不会抛出。它只是返回一个指向现有元素的迭代器。

带有提示的 insert() 版本仅返回一个迭代器,与无提示版本不同,后者还返回值是否已插入或已存在的指示。

CPP Reference 建议使用 size() 的变化来确定插入是否成功。我们可以尝试类似的

// untested
template<class K, class V, class C, class A, class Element>
auto insert(std::map<K,V,C,A>& map,
            std::map<K,V,C,A>::const_iterator hint,
            Element&& element)
{
     auto const initial_size = map.size();
     auto const it = map.insert(hint, std::forward<Element>(element));
     auto const was_added = map.size() != initial_size;
     return std::pair{it, was_added};
}

实际上,对于问题中的示例(构造一个键值对),我们可能希望包装 emplace_hint() 成员函数,因此我们可以传递一对或单独的键和值:

// untested
template<class K, class V, class C, class A, class... Args>
auto emplace(std::map<K,V,C,A>& map,
             std::map<K,V,C,A>::const_iterator hint,
             Args&&... args)
{
     auto const initial_size = map.size();
     auto const it = map.emplace_hint(hint, std::forward<Args>(args)...);
     auto const was_added = map.size() != initial_size;
     return std::pair{it, was_added};
}

insert() throws std::bad_alloc if it tried to insert but failed; if it chose not to insert because a value with that key already exists, then it does not throw. It just returns an iterator to the existing element.

The version of insert() that takes a hint just returns an iterator, unlike the non-hinted version which also returns an indication of whether the value was inserted or was already present.

CPP Reference suggests using change of size() to determine whether the insert was successful. We could try something like

// untested
template<class K, class V, class C, class A, class Element>
auto insert(std::map<K,V,C,A>& map,
            std::map<K,V,C,A>::const_iterator hint,
            Element&& element)
{
     auto const initial_size = map.size();
     auto const it = map.insert(hint, std::forward<Element>(element));
     auto const was_added = map.size() != initial_size;
     return std::pair{it, was_added};
}

Actually, for the example in the question (which constructs a key-value pair), we probably want to be wrapping the emplace_hint() member function, so we could pass either a pair or separate key and value:

// untested
template<class K, class V, class C, class A, class... Args>
auto emplace(std::map<K,V,C,A>& map,
             std::map<K,V,C,A>::const_iterator hint,
             Args&&... args)
{
     auto const initial_size = map.size();
     auto const it = map.emplace_hint(hint, std::forward<Args>(args)...);
     auto const was_added = map.size() != initial_size;
     return std::pair{it, was_added};
}
淡淡绿茶香 2024-10-26 04:53:44

比较插入前和插入后地图的大小,以了解插入元素是否很慢(Debian 8中的map::size很慢:浏览完整地图)

可以知道是否在地图中插入或找到了一对使用提示插入后无需重新计算大小,使用提示插入方法。

使用提示方法插入另一对相同的第一个,以及您确定不在映射中的第二个(如 -1 表示正第二个整数的映射)。如果返回的迭代器具有这个不可能的值,则它是新插入的,如果不是,则它是在映射中找到的。然后返回的迭代器可能会被更改。
示例:在map中插入对p (2,4) 和p (6, 5)米 ((0, 1), (2, 3), (4, 5))。

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; (2, 4) 来自第二个迭代器的

后在映射 m 中

一对具有这样的第一个在插入对 1 == 0->1 2->3 4->5

插入对 2 == std:: 对(6, 5) 从第三个迭代器

插入m

开始,该对在插入对 2 == 0->1 2->3 4->5 6->5 之后

Comparing the size of the map before insertion and after insertion to know if an element was inserted is slow (map::size is slow with Debian 8: browsing complete map)

It is possible to know whether a pair was inserted or found in a map after insertion with hint without recalculating size, using hint insertion method.

Insert with hint method another pair of the same first, and of a second that you are sure is not in the map ( like -1 for a map of positive second int). If the iterator returned has this impossible value, it has been newly inserted, if not it was found in the map. The iterator returned may then be changed.
Example : to insert pairs p (2,4) and p (6, 5) in the map<int, int> m ((0, 1), (2, 3), (4, 5)).

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;
}

outputs :
initial map == 0->1 2->3 4->5

insertion of pair 1 == std::pair<int, int> (2, 4) from second iterator

a pair with such a first was in the map

m after insertion of pair 1 == 0->1 2->3 4->5

insertion of pair 2 == std::pair<int, int> (6, 5) from third iterator

the pair was inserted

m after insertion of pair 2 == 0->1 2->3 4->5 6->5

最美的太阳 2024-10-26 04:53:44

根据 文档, std::map insert 返回一对两个值:“插入元素(或阻止插入的元素)的迭代器和当且仅当插入发生时设置为 true 的 bool 值。”

根据您用于映射的类型,您可以执行类似于上面建议的 Tristram 的操作,您可以在其中创建结果对。但是,如果您只想要其中一个值(例如,表明插入是否成功的布尔值),则类似这样的事情可能会更简单:

如果您只想要布尔值,则可以这样做

bool insert_completed = (mymap.insert({key,value})).second;

,或者如果您只想要迭代器,则可以这样做 这基本上是

auto inserted_iterator = (mymap.insert({key,value})).first;

说“嘿,我刚刚从 insert() 中得到了一对,我只关心该对中的一个,所以让我设置一些等于该块的变量”。

但是,请注意,这并不适用于 insert() 的每个版本。有些 insert 的返回值只是迭代器,有些不返回任何内容,甚至返回一个 insert_return_type,因此请检查文档以了解哪种特定情况与您正在编写的代码相关。

According to the documentation, std::map insert returns a pair of two values: "an iterator to the inserted element (or to the element that prevented the insertion) and a bool value set to true if and only if the insertion took place."

Depending on the types you are using for mapping, you can potentially do something like what Tristram suggested above, where you create a result pair. However, if you only want one of the values (e.g. the bool that states whether insertion was successful or not), something like this might be simpler:

If you only want the bool, you can do

bool insert_completed = (mymap.insert({key,value})).second;

or if you only want the iterator, you can do

auto inserted_iterator = (mymap.insert({key,value})).first;

This basically says "hey, I just got a pair as a result from insert(), I only care about one piece of that pair, so let me set some variable equal to that piece".

However, note that this doesn't work with every version of insert(). Some return values from insert are only the iterator, some return nothing, one even returns an insert_return_type, so please check the documentation to see which particular case is relevant to the code you're writing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文