c ++ вставить пустой вектор не может использовать фигурные скобки - PullRequest
3 голосов
/ 09 июля 2020

Коды ниже не работают должным образом, когда я ссылаюсь на it, это вызывает Member call on null pointer error, если он не поддерживается, почему он позволяет использовать insert(end, {}) (без ошибок компиляции).

#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector<vector<pair<int, int>>> vv;
    auto it = vv.insert(vv.end(), {});
    cout << it->size() << endl;
}

Когда я изменил {} to vector<pair<int, int>>, ошибки не отображаются и печатаются 0.

Решено с помощью комментариев, он вызывает iterator insert( const_iterator pos, std::initializer_list<T> ilist ), поэтому изменить его на insert(end, {{}}) можно.

Ответы [ 2 ]

2 голосов
/ 09 июля 2020

Согласно cppreference - std :: vector :: insert () , все разновидности insert() возвращают итератор первого вставленного элемента или позицию вставки, если ничего не было вставлено.

В OP открытые MCVE:

#include <vector>
#include <iostream>
using namespace std;
int main() {
    vector<vector<pair<int, int>>> vv;
    auto it = vv.insert(vv.end(), {});
    cout << it->size() << endl;
}

в строке

auto it = vv.insert(vv.end(), {});

не используется iterator insert( const_iterator pos, const T& value ); как и следовало ожидать, но iterator insert( const_iterator pos, std::initializer_list<T> ilist );.

Следовательно, вставлено 0 элементов, и insert() возвращает итератор end(), который был передан.

Итак,

cout << it->size() << endl;

обращений содержимое end(), которое является неопределенным поведением.

Я сделал небольшой образец, чтобы продемонстрировать это:

#include <initializer_list>
#include <iostream>
#include <vector>

template <typename T>
struct Container: std::vector<T> {
  using typename std::vector<T>::iterator;
  using typename std::vector<T>::const_iterator;
    
  iterator insert( const_iterator pos, const T& value )
  {
    std::cout << "insert single value\n";
    return std::vector<T>::insert(pos, value);
  }
  
  iterator insert( const_iterator pos, std::initializer_list<T> ilist )
  {
    std::cout << "insert initializer list\n";
    return std::vector<T>::insert(pos, ilist);
  }
};

using namespace std;
int main() {
    Container<vector<pair<int, int>>> vv;
    auto it = vv.insert(vv.end(), {});
    cout << /*it->*/vv.size() << endl;
}

Вывод:

insert initializer list
0

Live Demo на coliru

Примечание:

Я знаю, что, по крайней мере, перегружать std::vector - плохой стиль. Я сделал это исключительно для того, чтобы показать используемый вызов функции (и у меня не было лучшего представления, как этого добиться).

1 голос
/ 09 июля 2020

Строка auto it = vv.insert(vv.end(), {}); использует форму iterator insert( const_iterator pos, std::initializer_list<T> ilist );.

Как int строка auto it = vv.insert(vv.end(), {});, список инициализатора не имеет элемента, поэтому элемент не вставляется в вектор vv.

Поскольку элемент не вставлен, it совпадает с vv.end(), для которого он недопустим для уважения.

Вы можете проверить это, проверив длину vv после прошивки. См. Пример кода здесь , чтобы проверить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...