`std::back_inserter` 和 `std::inserter` 都是 C++ 标准库中的插入迭代器,用于向容器中插入元素。它们的主要区别在于插入元素的位置和适用的容器类型。
`std::back_inserter`
`std::back_inserter` 创建一个插入迭代器,该迭代器将新元素插入到容器的末尾。它适用于支持 `push_back` 成员函数的容器,如 `std::vector`、`std::deque` 和 `std::list`。
示例代码```cpp
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
int main() {
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5, 6};
// 使用 std::back_inserter 将 vec2 的元素插入到 vec1 的末尾
std::copy(vec2.begin(), vec2.end(), std::back_inserter(vec1));
// 输出结果
for (int n : vec1) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
`std::inserter`
`std::inserter` 创建一个插入迭代器,该迭代器将新元素插入到指定的位置。它适用于所有支持 `insert` 成员函数的容器,如 `std::vector`、`std::deque`、`std::list`、`std::set` 和 `std::map`。
示例代码
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
int main() {
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5, 6};
// 使用 std::inserter 将 vec2 的元素插入到 vec1 的第二个位置
std::copy(vec2.begin(), vec2.end(), std::inserter(vec1, vec1.begin() + 1));
// 输出结果
for (int n : vec1) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
区别总结
1. **插入位置**:
- `std::back_inserter`:将新元素插入到容器的末尾。
- `std::inserter`:将新元素插入到指定的位置。
2. **适用容器**:
- `std::back_inserter`:适用于支持 `push_back` 成员函数的容器,如 `std::vector`、`std::deque` 和 `std::list`。
- `std::inserter`:适用于所有支持 `insert` 成员函数的容器,如 `std::vector`、`std::deque`、`std::list`、`std::set` 和 `std::map`。
通过了解这两种插入迭代器的区别,可以根据具体需求选择合适的插入迭代器来操作容器。
Iterator types
std::back_inserter
returnsstd::back_insert_iterator
that usesContainer::push_back()
.std::inserter
returnsstd::insert_iterator
that usesContainer::insert()
.
std::list
For lists std::list::push_back
is almost the same as std::list::insert
. The only difference is that insert returns iterator to inserted element.
bits/stl_list.h
void push_back(const value_type& __x)
{ this->_M_insert(end(), __x); }
void _M_insert(iterator __position, const value_type& __x)
{
_Node* __tmp = _M_create_node(__x);
__tmp->_M_hook(__position._M_node);
}
bits/list.tcc
template<typename _Tp, typename _Alloc> typename list<_Tp, _Alloc>::iterator
list<_Tp, _Alloc>::insert(iterator __position, const value_type& __x)
{
_Node* __tmp = _M_create_node(__x);
__tmp->_M_hook(__position._M_node);
return iterator(__tmp);
}
std::vector
It looks a little different for std::vector
. Push back checks if reallocation is needed, and if not just places value in correct place.
bits/stl_vector.h
void push_back(const value_type& __x)
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x);
++this->_M_impl._M_finish;
}
else
_M_insert_aux(end(), __x);
}
But in std::vector::insert
there are 3 additional things done and it impacts performance. bits/vector.tcc
template<typename _Tp, typename _Alloc> typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::insert(iterator __position, const value_type& __x)
{
const size_type __n = __position - begin(); //(1)
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
&& __position == end()) //(2)
{
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x);
++this->_M_impl._M_finish;
}
else
{
_M_insert_aux(__position, __x);
}
return iterator(this->_M_impl._M_start + __n); //(3)
}