Зачем нужен аргумент списка в развлечении сращивания списка c cpp - PullRequest
2 голосов
/ 30 мая 2020

Зачем нам нужен аргумент списка в игре splice c cpp? Почему одних итераторов недостаточно? Результат будет таким же, если я передам l1 или l2 в качестве второго аргумента l1.splice(st, l1, it, it2); или l1.splice(st, l2, it, it2);

печатает 1 4 5 2 3

#include <bits/stdc++.h> 
using namespace std; 

int main() 
{ 


// initializing lists and iterator 
list<int> l1 = { 1, 2, 3 }; 
list<int> l2 = { 4, 5 }; 

auto it = l2.begin(); 
auto it2 = l2.end(); 

auto st = l1.begin();
std::advance(st,1);

// result the same if in splice l1 or l2
// 1 4 5 2 3 
l1.splice(st, l2, it, it2); 

cout << "list l1 after splice operation" << endl; 
for (auto x : l1) 
    cout << x << " "; 
return 0; 
} 

1 Ответ

1 голос
/ 30 мая 2020

Этот вызов

l1.splice(st, l1, it, it2);

вызывает неопределенное поведение.

Когда вам нужно извлечь диапазон элементов, тогда должны быть обновлены другие элементы данных списка, например size.

Если вы выполните, например, этот оператор

std::cout << l2.size() << '\n';

, вы можете получить неожиданный результат.

Вот демонстрационная программа, скомпилированная с g cc 8.3.

#include <iostream>
#include <list>
#include <iterator>

int main() 
{
    std::list<int> lst1 = { 1, 3, 5, 7, 9 };
    std::list<int> lst2 = { 0, 2, 4, 6, 8 };

    lst1.splice( std::next( std::begin( lst1 ) ), 
                            lst1, 
                            std::begin( lst2 ),
                            std::end( lst2 ) );

    for ( const auto &item : lst1 )
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';

    for ( const auto &item : lst2 )
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';

    std::cout << "the size of lst2 is " << lst2.size() << '\n';

    return 0;
}

Его вывод будет

1 0 2 4 6 8 3 5 7 9 

the size of lst2 is 5

Если вы измените lst1 на lst2 в этом вызове

    lst1.splice( std::next( std::begin( lst1 ) ), 
                            lst2,                 // <=== 
                            std::begin( lst2 ),
                            std::end( lst2 ) );

, то вы получите правильный результат

1 0 2 4 6 8 3 5 7 9 

the size of lst2 is 0 
                   ^^^
...