c++插入空向量不能使用大括号

c++ insert empty vector can not use braces

下面的代码不能正常工作,当我引用 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, {{}})可以工作。

auto it = vv.insert(vv.end(), {}); 行使用的格式是 iterator insert( const_iterator pos, std::initializer_list<T> ilist );

作为第 auto it = vv.insert(vv.end(), {}); 行的 intlizer 列表没有元素,因此没有元素插入向量 vv

因为没有插入元素,所以itvv.end()一样,不能引用。

插入后可以通过检查vv的长度来验证。请参阅 sample code here 进行检查。

根据cppreference – std::vector<T,Allocator>::insert(),所有类型insert() return第一个插入元素的迭代器或者没有插入时的插入位置。

在暴露 MCVE 的 OP 中:

#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() return 是传递的 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 on coliru

注:

我知道重载至少是一种糟糕的风格 std::vector。 我这样做是为了展示所使用的函数调用(我不知道如何实现这一点)。