Удаление из std::list

206
26 января 2018, 23:24

Нужно удалить элемент из std::listпо итератору. Стандарт С++11 и выше не используется. То есть имеется только функция iterator std::list::erase( iterator first, iterator last );

Если я сделаю так, то элемент не удалиться:

void func(std::list<int>& l, std::list<int>::iterator it)
{
    l.erase(it, ++it);
}

А если так, то все работает:

void func(std::list<int>& l, std::list<int>::iterator it)
{
    std::list<int>::iterator it2 = it;
    std::advance(it2, 1);
    l.erase(it, it2);
}

Почему? Ведь в erase в обоих случаях передаются одинаковые итераторы. Есть ли какой способ удалить один элемент из списка без лишних действий?

Answer 1

Вы столкнулись с неопределённым поведением.

Дело в том, что компилятор имеет право вычислять значения аргументов функции в любом порядке. Так что в первом случае он может сначала вычислить и подставить значение второго аргумента (++it), и только потом — первого (it).

Во втором же случае значение it2 вычисляется гарантировано до его использования в строке l.erase(it, it2); благодаря (грубо говоря) наличию точки с запятой.

Всё это является следствием работы механизма точек следования. Подробнее о нём можно почитать, например, в статье «Точки следования (sequence points)» в блоге «Алёна C++».

Answer 2

Порядок вычисления и передачи аргументов в функции не определен. Т.е. компилятор может, например, сначала вычислить ++i, а потом передавать значение.

Например,

#include <iostream>
#include <iomanip>
using namespace std;

void f(int a, int b)
{
    cout << a << " " << b << endl;
}
int main(int argc, const char * argv[])
{
    int i = 3;
    f(i,++i);
}

здесь, при том, что вы ожидаете 3 4, реально может быть 4 4 - и не только может, но и VC++, и GCC именно такой результат и дают.

P.S. См. понятие "точка следования".

READ ALSO
подключение #include &lt;pwd.h&gt; #include &lt;grp.h&gt; ошибка)))

подключение #include <pwd.h> #include <grp.h> ошибка)))

почему при компиляции выдает ошибку где я подключаю

218
C++ вызов функции каждую секунду

C++ вызов функции каждую секунду

Нужно создать функцию, которая будет вызываться каждую секунду и выполнять определенные действияБез sleep, ибо программа должна выполнять...

221
Вывод .tif файлов после выбора папки из QComboBox

Вывод .tif файлов после выбора папки из QComboBox

Необходимо при выборе папки из QComboBox, показать файлыtif из данной папки в listView

221
Русский текст из getwindowtext

Русский текст из getwindowtext

В Qt 48 вызываю функцию getwindowtext, которая во второй параметр выдает заголовок окна

220