#c #stl
#c #stl
Вопрос:
Я попытался отсортировать новый вектор после слияния двух векторов, вот такой код,
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
void vec_output(vector <int> vec_input)
{
for (int i = 0; i < vec_input.size(); i )
{
cout << vec_input[i] << ' ';
}
cout << endl;
}
int main(){
vector <int> v1{2,3,1};
vector <int> v2{5,4,6};
vector <int> v3;
set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
sort(v3.begin(), v3.end());
vec_output(v3);
return 0;
}
Однако он показывает ошибку: Exception has occurred. Segmentation fault
, я знаю, что это может быть вызвано доступом к неизвестной памяти, но как?
Комментарии:
1. проверьте: en.cppreference.com/w/cpp/algorithm/set_union , вам необходимо указать std::back_inserter(v3) в set_union()
2. Помимо этой проблемы,
std::set_union
работает с отсортированными диапазонами. Ваш векторv1
не отсортирован. Поведение не определено. Также бессмысленно вызыватьstd::sort
результирующее объединение, поскольку оно уже будет отсортировано.3. Вы читали документацию ? Подсказка:
std::back_inserter(v3)
. Кроме того, неудивительно,.begin()
что в пустом векторе получается что-то, что действительно только для сравнений.end()
, но не для (попыток) разыменования. И последнее, но не менее важное:using namespace std;
это антипаттерн, пожалуйста, не делайте этого.4. @AndrejPodzimek Я собираюсь удвоить рекомендацию, чтобы избежать
using namespace std
. Вместо этого просто извлеките нужные вам фрагменты, напримерusing std::vector
.5.
std::set_union()
, как и ряд других алгоритмов, предполагает, что последний аргумент является итератором с возможностью разыменования.v3
не имеет элементов, поэтомуv3.begin()
будет равноv3.end()
и разыменование его (для записи значения через него) дает неопределенное поведение. Используйтеstd::back_inserter(v3)
вместо этого — это создает итератор, к которому будут добавляться элементыv3
.
Ответ №1:
Проблема в том, что v3
пусто, поэтому запись v.begin()
в качестве последнего аргумента set_union
невозможна. Вы должны использовать back_inserter
как:
set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3));
std::back_inserter
Вернет итератор вывода back_insert_iterator
, который будет использоваться v3.push_back
для добавления / возврата элементов v3
.
Кроме того, из документации std::set_union:
Элементы сравниваются с помощью operator<, и диапазоны должны быть отсортированы по одному и тому же.
(Выделение мое)
Также обратите внимание, что после использования set_union
вам не нужно использовать std::sort
on v3
.
Комментарии:
1. Это не полная история. Если
set_union
вызывается для диапазонов, которые не отсортированы (v1
иv2
), поведение не определено.2. Вы также должны добавить, что сортировка вывода set_union не требуется.
3. Нет необходимости в итераторе вставки, если `v3` инициализирован с правильным размером.