Как эта строка в следующей программе содержит итератор для конкретного элемента? - PullRequest
2 голосов
/ 06 июля 2019

Я видел следующую программу на cplusplus.com .

// set::insert (C++98)
#include <iostream>
#include <set>

int main ()
{
  std::set<int> myset;
  std::set<int>::iterator it;
  std::pair<std::set<int>::iterator,bool> ret;

  // set some initial values:
  for (int i=1; i<=5; ++i) myset.insert(i*10);    // set: 10 20 30 40 50

  ret = myset.insert(20);               // no new element inserted

  if (ret.second==false) it=ret.first;  // "it" now points to element 20

  myset.insert (it,25);                 // max efficiency inserting
  myset.insert (it,24);                 // max efficiency inserting
  myset.insert (it,26);                 // no max efficiency inserting

  int myints[]= {5,10,15};              // 10 already in set, not inserted
  myset.insert (myints,myints+3);

  std::cout << "myset contains:";
  for (it=myset.begin(); it!=myset.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

Вывод этой программы:

myset contains: 5 10 15 20 24 25 26 30 40 50

В строке 16 th комментарий говорит, что std::set<int>::iterator it теперь указывает на элемент 20, второй элемент в наборе. Но я, похоже, не понимаю, почему так происходит или как на самом деле работает утверждение if (ret.second==false) it=ret.first;.

Было бы очень полезно, если бы кто-нибудь объяснил мне, как работает этот код. Тем не менее, можно иметь в виду, что я новичок в std::set.

Ответы [ 2 ]

5 голосов
/ 06 июля 2019

Из ссылки :

Возвращает пару, состоящую из итератора для вставленного элемента (или для элемента, который предотвратил вставку) и значение bool, установленное в значение true, если вставка произошла.

Поскольку набор в вашем примере уже содержит элемент 20, итератор к нему возвращается.

Это объясняется тем, что часть алгоритма вставки находит место для этого нового элемента. Это место, очевидно, такое же, как и то, где бы мы его искали, если бы оно было в контейнере.

Итак, опять же, мы смотрим, где это должно быть, если его там нет, мы помещаем его туда. Если это так, то мы просто возвращаем итератор в это место. Эта дополнительная операция тогда в основном бесплатна.

4 голосов
/ 06 июля 2019

один элемент (1): pair<iterator,bool> insert (const value_type& val);

Версии одного элемента (1) возвращают пару с ее парой-членом: :: first, установленной на итератор, указывающий либо на недавно вставленный элемент, либо на эквивалентный элемент, уже находящийся в наборе. Элемент pair :: second в паре имеет значение true, если новый элемент был вставлен, или false, если эквивалентный элемент уже существует.

Приведенный выше парафраз из http://www.cplusplus.com/reference/set/set/insert/ очищает все.

for (int i=1; i<=5; ++i) myset.insert(i*10); Здесь 20 уже вставлено.

И снова вы пытаетесь вставить 20, который уже существует, поэтому insert возвращает pair, содержащий iterator и false, т.е. pair second термин false.

P.S. Если вы используете современные стандарты C ++, такие как (C ++ 11, 14, 17 или 20), вам следует обратиться к https://en.cppreference.com/w/, так как он обновлен.

...