《C++标准程序库》 第4章 通用工具
第1~3章 略
std::pair 是一个 struct ,定义于 bits/stl_pair.h 文件中,被包含进 <utility> 头文件中。
std::make_pair(42,'@') //相当于 std::pair<int,char> (42,'@') std::pair<int,int> p = std::make_pair(42,3.3); //42,3
任何函数需要返回两个值,必须使用 pair; 标准程序库中 map 和 multimap 容器的元素型别也是 pair。
std::auto_ptr<int> p(new int(3)); 定义于 backward/auto_ptr.h 文件中,被包含进 <memory>头文件中。
auto_ptr 要求一个对象只有一个拥有者,绝对不应该出现多个 auto_ptr 拥有一个对象的情况。如:
std::auto_ptr<int> p1(p); std::cout<<*p1<<std::endl; //OK std::cout<<*p<<std::endl; //段错误
auto_ptr 的 copy 构造函数 和 assignment 操作符会将对象拥有权交出去。
程序员需要自己来保证那个”失去了所有权、只剩下一个 null 指针“的原 auto_ptr 不会再次被进行提领动作。
将 auto_ptr 作为函数参数或函数返回值,一定要特别注意所有权问题。比如:
std::auto_ptr<int> p(new int(42)); fun(p); //p的所有权已经转交出去 *p = 18; //error
不要试图使用 pass by reference 方式来传递 auto_ptr ,因为你根本无法预知拥有权是否被转交。
如果用 const 来修饰一个 auto_ptr ,并非意味着不能更改它拥有的对象,而是意味着你不能更改 auto_ptr 的所有权。
auto_ptr 的注意点:
1、auto_ptr 之间不能共享拥有权,一个 auto_ptr 不能指向另一个 auto_ptr 所拥有的对象。
2、并不存在针对 array 而设计的 auto_ptr,因为 auto_ptr 是通过 delete 而不是 delete [] 来释放对象的。
3、它的通用性不强,它不是引用计数型指针。
4、auto_ptr 不满足 STL 容器对元素的要求,比如拷贝和赋值动作。
C++11标准已经废弃了 auto_ptr ,取而代之的是 unique_ptr。
数值极限(Numeric Limits)是与平台有关的,C++标准库通过 template numeric_limits 提供这些极值,取代传统C语言所采用的预处理器常数。前者定义于头文件 <limits> 中,后者整数常数定义于 <climits> 和 <limits.h>,浮点常数定义于 <cfloat> 和 <float.h> 中,推荐使用前者,有更好的型别安全性。
numeric_limits 中提供了通用性的 template 和特化版本,如:
template <class T> class numeric_limits {...}; template <> class numeric_limits<int> {...};
使用示例如下:
#include <iostream> #include <limits> #include <string> int main() { std::cout<<std::numeric_limits<int>::is_specialized<<std::endl; //是否有极值 std::cout<<std::numeric_limits<int>::max()<<std::endl; std::cout<<std::numeric_limits<int>::min()<<std::endl; std::cout<<std::numeric_limits<std::string>::is_specialized<<std::endl; std::cout<<std::numeric_limits<std::string>::max()<<std::endl; //Error! }
在两个值之间挑选较大值和较小值的辅助函数,定义于 <bits/stl_algobase.h> ,被包含进 <algorithm> 头文件。源码如下:
template<typename _Tp> inline const _Tp& max(const _Tp& __a, const _Tp& __b) { // concept requirements __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) //return __a < __b ? __b : __a; if (__a < __b) return __b; return __a; } template<typename _Tp, typename _Compare> inline const _Tp& max(const _Tp& __a, const _Tp& __b, _Compare __comp) { //return __comp(__a, __b) ? __b : __a; if (__comp(__a, __b)) return __b; return __a; }
min 函数实现类似,略。使用示例如下:
#include <iostream> #include <algorithm> struct User { User(int _id):id(_id){} bool operator<(const User& user2) const //这里只需要实现 operator< 即可 { return id < user2.id; } int id; }; bool compareUser(User user1,User user2) { return user1.id < user2.id; //要返回 第一个参数 < 第二个参数的 bool 值 } int main() { User user1(3),user2(2); std::cout<<std::max(user1,user2).id<<std::endl; std::cout<<std::max(user1,user2,compareUser).id<<std::endl; }
有四个比较操作符的 template functions ,分别定义了 !=, >, <=, >= ,它们都是利用操作符 == 和 < 完成的,定义于头文件 <utility>,位于命名空间 std::rel_ops;
namespace std { namespace rel_ops { template <class T> inline bool operator!=(const T& x, const T& y) { return !(x == y); } template <class T> inline bool operator>(const T& x, const T& y) { return x < y; } template <class T> inline bool operator<=(const T& x, const T& y) { return !(y < x); } template <class T> inline bool operator>=(const T& x, const T& y) { return !(x < y); } } }
只需要定义 < 和 == 操作符,然后 using namespace std::rel_ops; 上述四个操作符就自动获得了定义。
#include <iostream> #include <utility> struct User { User(int _id):id(_id){} bool operator==(const User& user) const { return id == user.id; } bool operator<(const User& user) const { return id < user.id; } int id; }; int main() { using namespace std::rel_ops; User user1(3),user2(4); std::cout<<(user1>user2)<<std::endl; }