set特性
set所有元素都会根据元素的键值自动被排序,set元素的键值就是实值,实值就是键值。
set不可通过迭代器修改set元素值,set元素值就是其键值,关系到set元素的排列规则,源码中set<T>::iterator被定义为底层RB-tree的const_iterator,杜绝写入操作。
STL特别提供了一组set/mulset的相关算法,包括交集set_intersection、联集set_union、差集set_difference、对称差集set_symmetric_difference。
set与list相同的性质:元素新增(insert)和删除(erase)操作时,操作之前的所有迭代器,在操作之后依然有效,被删除元素的迭代器除外。
set以RB-tree为底层机制,set开放的各种接口几乎是转调用RB-tree的操作行为。
map特性
所有元素会根据元素的键值自动被排序,map的所有元素都是pair,同时拥有键值key和实值value,map元素键值不可相同。
map的键值不可修改,实值可以修改,因此map的迭代器既不是constant iterators,也不是mutable iterators。
map与list相同的性质:元素新增(insert)和删除(erase)时,操作之前的所有迭代器,在操作之后依然有效,被删除元素的迭代器除外。
map以RB-tree为底层机制,map开放的各种接口几乎是转调用RB-tree的操作行为。
插入操作,返回一个pair,第一个元素是个迭代器,指向插入成功的新元素或插入失败键值重复的旧元素,第二个元素返回插入成功或失败的bool值。
下标运算符,用法有两种,可能作为左值运用内容可被修改,也可能作为右值使用内容不可被修改。
下标运算符,先插入键值和临时实值对象,插入操作返回一个pair,第一个元素是个迭代器,指向插入成功的新元素或插入失败(键值重复)的旧元素。下标运算符作为左值使用时,正好赋值新插入点实值;下标运算作右值使用时,返回插入失败键值重复旧元素的实值。
multiset特性
multiset特性和用法与set完全相同,唯一差别在于它允许键值重复,因此它的插入操作采用的是底层RT-tree的insert_equal()而不是insert_unique()。
multimap
multimap的特性和用法与map完全相同,唯一差别在于它允许键值重复,因此它的插入操作采用的是底层RT-tree的insert_equal()而不是insert_unique()。
下面stl_pari的pair定义
namespace std _GLIBCXX_VISIBILITY(default)
{
/// piecewise_construct_t
struct piecewise_construct_t { };
constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
// Forward declarations.
template<typename...>
class tuple;
template<std::size_t...>
struct _Index_tuple;
template<class _T1, class _T2>
struct pair
{
typedef _T1 first_type; /// @c first_type is the first bound type
typedef _T2 second_type; /// @c second_type is the second bound type
_T1 first; /// @c first is a copy of the first object
_T2 second; /// @c second is a copy of the second object
_GLIBCXX_CONSTEXPR pair() //默认构造函数
: first(), second() { }
_GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
: first(__a), second(__b) { }
/** There is also a templated copy ctor for the @c pair class itself. */
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<const _U1&, _T1>,
is_convertible<const _U2&, _T2>>::value>::type>
constexpr pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
constexpr pair(const pair&) = default;
constexpr pair(pair&&) = default;
template<class _U1, class = typename
enable_if<is_convertible<_U1, _T1>::value>::type>
constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }
template<class _U2, class = typename
enable_if<is_convertible<_U2, _T2>::value>::type>
constexpr pair(const _T1& __x, _U2&& __y)
: first(__x), second(std::forward<_U2>(__y)) { }
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
constexpr pair(_U1&& __x, _U2&& __y)
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
template<class _U1, class _U2, class = typename
enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>>::value>::type>
constexpr pair(pair<_U1, _U2>&& __p)
: first(std::forward<_U1>(__p.first)),
second(std::forward<_U2>(__p.second)) { }
template<typename... _Args1, typename... _Args2>
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
pair&
operator=(const pair& __p)
{
first = __p.first;
second = __p.second;
return *this;
}
pair&
operator=(pair&& __p)
noexcept(__and_<is_nothrow_move_assignable<_T1>,
is_nothrow_move_assignable<_T2>>::value)
{
first = std::forward<first_type>(__p.first);
second = std::forward<second_type>(__p.second);
return *this;
}
template<class _U1, class _U2>
pair&
operator=(const pair<_U1, _U2>& __p)
{
first = __p.first;
second = __p.second;
return *this;
}
template<class _U1, class _U2>
pair&
operator=(pair<_U1, _U2>&& __p)
{
first = std::forward<_U1>(__p.first);
second = std::forward<_U2>(__p.second);
return *this;
}
void
swap(pair& __p)
noexcept(noexcept(swap(first, __p.first))
&& noexcept(swap(second, __p.second)))
{
using std::swap;
swap(first, __p.first);
swap(second, __p.second);
}
private:
template<typename... _Args1, std::size_t... _Indexes1,
typename... _Args2, std::size_t... _Indexes2>
pair(tuple<_Args1...>&, tuple<_Args2...>&,
_Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>);
};
/// Two pairs of the same type are equal iff their members are equal.
template<class _T1, class _T2>
inline _GLIBCXX_CONSTEXPR bool
operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __x.first == __y.first && __x.second == __y.second; }
template<class _T1, class _T2>
inline _GLIBCXX_CONSTEXPR bool
operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __x.first < __y.first
|| (!(__y.first < __x.first) && __x.second < __y.second); }
/// Uses @c operator== to find the result.
template<class _T1, class _T2>
inline _GLIBCXX_CONSTEXPR bool
operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__x == __y); }
/// Uses @c operator< to find the result.
template<class _T1, class _T2>
inline _GLIBCXX_CONSTEXPR bool
operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return __y < __x; }
/// Uses @c operator< to find the result.
template<class _T1, class _T2>
inline _GLIBCXX_CONSTEXPR bool
operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__y < __x); }
/// Uses @c operator< to find the result.
template<class _T1, class _T2>
inline _GLIBCXX_CONSTEXPR bool
operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
{ return !(__x < __y); }
template<class _T1, class _T2>
inline void
swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); }
template<class _T1, class _T2>
constexpr pair<typename __decay_and_strip<_T1>::__type,
typename __decay_and_strip<_T2>::__type>
make_pair(_T1&& __x, _T2&& __y)
{
typedef typename __decay_and_strip<_T1>::__type __ds_type1;
typedef typename __decay_and_strip<_T2>::__type __ds_type2;
typedef pair<__ds_type1, __ds_type2> __pair_type;
return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
}
} // namespace std