这个链接可能对你有用:小站入口 CSDN入口
/*************************重载运算符****************/
template
bool operator==(const pair& lhs, const pair& rhs)
{
return lhs.first == rhs.first && lhs.second == rhs.second;
}
template
bool operator!=(const pair& lhs, const pair& rhs)
{
return !(lhs == rhs);
}
template
bool operator<(const pair& lhs, const pair& rhs)
{
return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second);
//优先比较first
}
template
bool operator>(const pair& lhs, const pair& rhs)
{
return rhs < lhs;
}
template
bool operator<=(const pair& lhs, const pair& rhs)
{
return !(rhs < lhs);
}
template
bool operator>=(const pair& lhs, const pair& rhs)
{
return !(lhs < rhs);
}
/*************************重载运算符****************/
重载==之后,重载!=可以直接利用==。
重载>之后,重载<,<=,>=可以利用>的重载。
如果不是看到源码,我可能会傻乎乎的一个一个写,而不会利用已经重载的运算符,这里给我一个小提示。在类的swap等函数中都用了这种小技巧,第一次见到,还是记录一下。
若问T1,T2是一个类pair无法重载怎么办,这需要在该类中重载运算,这不是pair应该纠结的事情。
template
void construct(Ty* ptr)
{
::new ((void*)ptr) Ty();
}
template
void construct(Ty1* ptr, const Ty2& value)
{
::new ((void*)ptr) Ty1(value);
}
在construct.h中看到这么一串代码,这里说一下Ty()和Ty(value),你可以认为是两个临时对象。第一个有默认值,第二个有一个初值。
对于类而言,就是一个临时对象。如果是一个数据类型,定义了一个右值对象。
我在编译器下测试如下:
class C
{
int x,y;
};
void fun(int &&x)
{
cout<<"右值引用"<
对于构造的临时对象,按道理是不会有内存空间的,但是这里要注意的是,输出的结果是1。
对于int() ,如果输出,值为0,这就是它的默认值。对于字符串,默认值为空串。
源码地址入口
// 五种迭代器类型
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
//不熟知的类 前面的是父类,箭头后面是子类
iterator
has_iterator_cat
iterator_traits_impl(有bool不同的两个版本)->iterator_traits_helper(有bool不同的两个版本) -> iterator_traits(有偏特化的多个版本)
| m_bool_constant(type_traits.h文件中的类) -> has_iterator_cat_of |
| m_false_type(type_traits.h文件中的类) -> has_iterator_cat_of |
has_iterator_cat_of -> is_input_iterator
-> is_output_iterator
-> is_forward_iterator
-> is_bidirectional_iterator
-> is_random_access_iterator(五个子类)
m_bool_constant -> is_iterator
上面是对类关系的一些提炼,不然要被各种类搞的玩迷宫一样。
在这里举一个例子来说明萃取机:
// 萃取某个迭代器的 value_type
template
typename iterator_traits::value_type*
value_type(const Iterator&)
{
return static_cast::value_type*>(0);
}
/* 传进去一个迭代器value_type(const Iterator&),问这个迭代器的value是什么类型啊?
iterator_traits做出解释: */
template
struct iterator_traits
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;
};
/* 哦,我知道了,原来是T啊! */
/*对于typedef可以看成是一问一答的形式,一层一层往上问,最底层的类给出答案,然后一层一层又传到疑问这里。
typedef A B ,问A的类型,这时候代码往上看,底层是什么,那么A就是什么。*/
对于计算迭代器间的距离,重载两个函数,一个是一步一步不能跳的,一个是可以跳的
// distance 的 input_iterator_tag 的版本
template
typename iterator_traits::difference_type
distance_dispatch(InputIterator first, InputIterator last, input_iterator_tag)
{ //Input
typename iterator_traits::difference_type n = 0;
while (first != last)
{
++first;
++n;
}
return n;
}
// distance 的 random_access_iterator_tag 的版本
template
typename iterator_traits::difference_type
distance_dispatch(RandomIter first, RandomIter last, //Random
random_access_iterator_tag)
{
return last - first;
}
//根据迭代器的类型选择哪个函数,根据函数的参数判断。
//advance差不多,多了个BidirectionalIterator,它可以后退,输入负数是可以的。
2020/7/1 未完结