C++标准库概览
C++标准库
一、C++标准变更
|
年份 |
正式名称 |
简称 |
|
1998 |
ISO/IEC 14882:1998 |
C++98 |
|
2003 |
ISO/IEC 14882:2003 |
C++03 |
|
2011 |
ISO/IEC 14882:2011 |
C++11 |
|
2014 |
ISO/IEC 14882:2014 |
C++14 |
|
2017 |
ISO/IEC 14882:2017 |
C++17 |
|
2020 |
Yet to be determined |
C++20 |
对于正在进行中的C++20,预计在2019年夏天完成所有功能。
1. C++98
1998年C++标准得到了国际标准化组织(ISO)美国标准化协会(ANSI)的批准,标准C++语言及其标准库体现了C++语言设计的初衷。此后C++是具有国际标准的编程语言,以后每5年视实际需要更新一次标准。
2. C++03
C++标准第二版,2003年发布,这个标准仅仅是C++98修订版,与C++98差别不大,没做什么更新,仅仅是对C++98做了一些勘误。
3. C++11
C++标准第三版,2011年8月12日发布,并于2011年9月出版。C++11包含了核心语言的新机能,并且拓展C++标准程序库,加入了大部分的C++ Technical Report 1程序库,此次标准为C++98发布后13年来第一次重大修正。
- 语言可用性的强化
l nullptr与constexpr:nullptr是内建标识符,表示空指针,不同于NULL,NULL只是一个常整数为0的宏;constexpr对const变量扩展,约束const变量右侧的式子必须在编译时就能算出值;
l 类型推导:auto、decltype(萃取类型)、结尾返回类型,auto与decltype配合;
l 区间迭代:基于范围的for循环,如:vector<int> m; for(auto p : m);
l 初始化列表:std::initializer_list、统一初始化语法;
l 模版增强:外部模版、右尖括号>、类型别名模版、变长参数模版;
l 面向对象增强:委托构造、继承构造、显示的虚函数重载(override:指定子类的虚函数是重写父类的,final:不需要某个类被继承,或者不希望某个虚函数被重写时可以在类名和虚函数后添加final关键字)、显示禁用默认函数(default:=default要求编译器生成一个默认的构造函数,delete:=delete 要求编译器不要生成某个默认函数);
l 强类型枚举:在标准C++中,枚举类型不是类型安全的。枚举类型被视为整数,这使得两种不同的枚举类型之间可以进行比较。C++11引进了一种特别的枚举类,可以避免上述问题,使用enum class的语法来声明。
- 语言运行期的强化
l lambda表达式:lambda表达式基础(值捕获、引用捕获、隐式捕获、表达式捕获)、泛型lambda。让C++具有匿名函数的闭包特性;
l 函数对象包装器:std::function、std::bind/std::placeholder;
l 右值引用:左值、右值的纯右值、将亡值、右值;移动语义(std::move将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存拷贝);完美转发;右值引用与左值引用。主要解决临时对象效率问题。
- 对标准库的扩充
l 新增容器:std::array(可保存在栈内存中)、std::forward_list(单向链表实现,插入元素复杂度O(1),不支持快速随机访问)、std::unordered_set(无序集合)、std:: unordered_map(无序映射)、std::tuple(基本操作、运行期索引、合并与迭代);
l 智能指针和引用计数:std::shared_ptr(内部引用计数是安全的,对象读取需要加锁)、std::make_shared、std::unique_ptr(独占的智能指针)、std::weak_ptr;
l 正则表达式库:正则表达式简介(普通字符、特殊字符、限定符)、std::regex、std::regex_match、std::match_results;
l 语言级线程支持:std::thread、std::mutex、std::unique_lock、std::future、std::packaged_task、std::condition_variable;
- 其它杂项
l 新类型:long long int;
l noexcept的修饰和操作;
l 字面量:原始字符串字面量和自定义字面量;
l 参数绑定:std::bind、std::function;
l 静态断言static_assert。
- 已弃用的特性
说明:弃用不等于废弃,只是用于暗示程序员这些特性将从未来的标准中消失,应该尽量避免使用。但是,已弃用的特性依然是标准库的一部分,并且出于兼容性的考虑,这些特性其实会永久保留。
l 如果一个类有析构函数,为其生成拷贝构造函数和拷贝赋值运算符的特性被弃用了;
l 不再允许字符串字面值常量赋值给一个char*。如果需要用字符串字面值常量赋值和初始化一个char*,应该使用const char*或者auto;
l C++98异常说明、unexcepted_handler、set_ unexcepted()等相关特性被弃用,应该使用noexcept;
l auto_ptr被弃用,应该使用unique_ptr;
l register关键字被弃用;
l bool类型的++操作被弃用;
l C语言风格的类型转换被弃用,应该使用static_cast、reinterpret_cast、const_cast来进行类型转换;
l 参数绑定(std::bind和std::function)、export也均被弃用。
4. C++14
C++标准第四版,2014年8月18日发布,C++14旨在作为C++11的一个小扩展,是对C++11的补充和优化,主要是支持普通函数的返回类型推算,泛型lambda,扩展的lambda捕获,对constexpr函数限制的修订,constexpr变量模版化等等。
- 新的语言特性
l 扩展constexpr:C++11引入了声明为constexpr的函数的概念,声明为constexpr函数的意义是:如果其参数均为合适的编译器常量,则对这个constexpr函数的调用就可以用于期望常量表达式的场合,如果参数的值在运行期才能确定,或者虽然参数的值是编译器常量,但不匹配这个函数的要求,则对这个函数调用的求值只能在运行期进行。C++14放松了这些限制,声明为constexpr函数可以含有以下内容:任何声明,除了static或thread_local变量和没有初始化的变量声明;支持条件分支语句if和switc;支持所有循环语句;
l 函数返回类型推导:auto和decltype(auto)作为返回类型;
l 泛型lambda:在C++11中,lambda函数的形式参数需要被声明为具体的类型,C++14放宽了这一要求,允许lambda函数的形式参数声明中使用类型说明符auto;
l lambda捕获部分中使用表达式:C++11的lambda函数通过值拷贝或引用捕获已在外层作用域声明的变量,这意味这lambda捕获的变量不可以是move-only的类型。C++14允许lambda成员用任意的捕获表达式初始化。这既允许了capture by value-move,也允许了任意声明lambda的成员,而不需要外层作用域有一个具有相应名字的变量;
l 二进制字面量:数字可以用二进制形式指定,格式用前缀0b或0B;
l 单引号用作数字分位符:使数值类型的字面量具有更好的可读性,如:¥100’000;
l 变量模版:将模版扩展到变量,如:pi<T>,根据T类型返回pi对应的值;
l 聚合类成员初始化:含有default member initializer的类型也允许聚合初始化;
l deprecated属性:deprecated属性允许标记不推荐使用的实体,该实体仍然能合法使用,但会让用户注意到使用它是不受欢迎的,并且可能会导致在编译期间给出警告消息。
- 新的标准库特性
l 共享的互斥体和锁:std::shared_timed_mutex;
l 元函数的别名:C++11定义了一组元素,用于查询一个给定类型是否具有某种特性,或者转换给定类型的某种特征,从而得到另一个类型。后一种元函数通过成员类型type来返回转换后的类型,当它们用在模版时,必须使用typename关键字,这会增加代码的长度。利用类型别名模版,C++14提供了更便捷的写法。其命名规则是:如果标准库的某个类模版只含有唯一的成员,那么标准库提供std::some_class<T>作为typename std::some_class::type的别名;
l 关联容器中的异构查找:C++标准库定义了四个关联容器类,set和multiset允许用户根据一个值在容器中查找对应的同类型的值。map和multimap容器允许用户指定key和值的类型,根据键进行查找并返回对应的值。然而查找只能接受指定类型的参数,在map和multimap中是键的类型,而在set和multiset容器中就是值本身的类型。C++14允许通过其它类型进行查找,只需要这个类型和实际的键类型之间可以进行比较操作;
l 标准自定义字面量:标准库定义了许多字面量后缀,如:”s”、”h“、”if”等;
l 通过类型寻址多元组:C++11引入的std::tuple类型允许不同类型的值的聚合体用编译期整形常数索引。C++14还允许使用类型代替常数索引,从多元组中获取对象,若多元组含有多余一个这个类型的对象,将会产生一个编译错误;
l 较小的标准库特性:std::make_unique可以像std::make_shared一样使用,用于产生std::unique_ptr对象;std::is_final用于识别一个class类型是否禁止被集成;std::integral_constant增加了一个返回常量值的operator();全局std::begin/std::end函数之外,增加了std::cbegin/std::cend函数,它们总是返回常量迭代器。
- 已弃用特性
l 关于数组的扩展:在C++11和之前的标准中,在堆栈上分配的数组被限制为拥有一个固定的、编译期确定的长度。这一扩展允许在对堆栈上分配一个数组的最后一维具有运行期确定的长度,运行期确定长度的数组不可以作为对象的一部分,也不可以具有全局存储期,它们只能被声明为局部变量。由于一些设计无法达成一致,这一扩展已被弃用;
l optional值:类似于C#中可空类型,optional类型可能含有或不含有一个值,这一类型基于boost的boost:: optional类,而添加了C++11和C++14中的新特性,诸如移动和inplace构造;
l concepts lite:被C++11拒绝后,concepts收到彻底的修改concepts lite是concepts的一个部分,仅包含类型约束,而不包含concept_map和axiom。
5. C++17
C++标准第五版,2017年11月30日发布,基于C++11,C++17旨在使C++成为一个不那么臃肿复杂的编程语言,使开发者可以更简单地编写和维护代码。C++17是对C++语言的重大更新,引入了许多新的语言特性。
- 删除或弃用的特性
l 删除trigraphs:三字符组,如:??=编译时会被替换为#;
l 删除register:register关键字仍然保留,不再具有任何语义;
l 删除bool类型的++运算:前自增和后自增运算符不再接收bool类型的操作数;
l 删除throw(A, B, C):形如throw(A, B, C)的动态异常规范(dynamic exception specification)不再是合法的,throw()保留,成为noexcept(true)的同义词。
l 弃用static constexpr成员的重复声明;
l 删除auto_ptr、random_shuffle、<functional>中的过时部分:在C++11已经被弃用并被更好的组件取名的功能将不再包含于C++17中。它们的名字仍然是保留的,实现可以选择继续提供;
l 删除被弃用的isotream成员;
l 删除std::function的内存分配器(allocated)支持:多态函数包装器function不再具有接收内存分配器的构造函数。内存分配器支持对既有类型擦除(type-erase)功能的可复制类型来说很困难,可能无法有效实现;
l 弃用一些C库头文件:“C库”指的C++标准库中的一部分,而不是C标准库中的一部分,弃用以下头文件,<ccomplex>、<cstdalign>、<cstdbool>和<cstdmath>;
l 弃用标准库中的陈旧部分:以下组件被弃用,allocator<void>、raw_storage_iterator、get_temporary_buffer、is_literal_type、std::iterator。
l 弃用<codecvt>:整个头文件被弃用(注意codecvt类并不在这个头文件中),wstring_convert和wbuffer_convert也被弃用,这些功能难以正确使用;
l 暂时弃用memory_order_consume:当前的“consumer”内存序的语义被发现是不够的,需要重新定义,建议使用”acpuire“内存序;
l 弃用shared_ptr::unique:该成员函数暗示了没有实际提供的行为;
l 弃用result_of:请改用新的trair::invoke_result。
- 全局影响的新的核心语言特性
l 异常规范(exception specification):函数的异常规范现在是函数类型的一部分,void f() noexcept(true);和void f() no noexcept(false);是具有不同类型的函数。函数指针可以按符合常理的方式转换(但是这两个函数f不能构成重载),这个变化加强了类型系统,例如,API可以通过类型系统要求回调函数不抛出异常;
l 保证的复制消除:prvalue和glvalue的含义已被修改,prvalue不再代表对象,而仅仅代表初始化。返回prvalue的函数不再复制对象,并且有了新的prvalue到glvalue的转换,叫做temporary materialization conversion。这个变化意味着复制消除是保证的,而且甚至可以应用于不可移动或复制的类型,允许你定义返回这种不可移动或复制的类型的函数;
l 过度对齐类型(over aligned types)的动态内存分配:alignment超过std::max_align_t的类型,动态内存分配(operator new)现在可以支持过度对齐的类型,这个运算符的一个新的重载接收对齐要求参数;
l 更严格的表达式求值顺序:对某些子表达式的求值顺序的规定更多了,这个变化的一个重要方面是函数的各个实参在以不确定的顺序的求值,而以前只是未指定的。注意,重载运算符的求值顺序和调用方式有关,如果按照运算符的形式调用,就和相应的内置运算符的顺序相同,如果按照函数调用的形式调用,就和一般的函数调用相同。
- 局部影响的新的核心语言特性
l u8字符字面量:具有u8前缀的字符字面量产生一个在UTF-8中占有一个编码单元(code unit)的合法unicode代码点(code point)对应的字符,换句话说,就是产生一个ASCII值,如:u8’x’;
l 十六进制浮点数字面量:具有十六进制底数和十进制指数的浮点数字面量,如:0xC.86p + 2.0x1.P-126;
l fold折叠表达式(fold expression):用于迭代地将二元运算符应用于参数包(parameter pack)的元素的便利语法;
l template<auto>:模版的非类型参数可以用占位符类型auto声明;
l 类模版参数推导:类模版的模版参数现在可以从构造函数推导;
l constexpr if:新的if constexpr (condition)语句根据常量表达式(constant expression)的值选择执行那个分支,在模版实例中,只有在条件具有合适值的时候,对应的分支才会实例化;
l 带初始化的选择语句:选择语句if和switch有了一个新的可选的初始化部分,如:if(auto it = m.find(key); it !=m.end()){…};
l constexpr lambda:lambda表达式现在可以是常量表达式了,如:auto add = [](int a, int b) constexpr { return a + b; }; int arr[add(1, 2)];
l lambda捕获*this:以前:[ self = *this ]{ self.f(); },现在:[ *this ]{ f(); };
l 内联变量(inline variables):允许在头文件中定义变量,如在头文件中,inline int n = 10; 所有定义都指代同一个实体。static constexpr成员变量隐含地成为inline变量(标准库中的常量,不论是已有的还是新增的,都已使用inline);
l 结构化绑定(structure binding):for(auto [key, value] : my_map){…};
l __has_include:检查能否包含特定头文件的预处理运算符;
l 新的标准属性(attribute)[[fallthrough]]、[[maybe_unused]]和[[nodiscard]];
l launder:语言支持工具(优化屏蔽optimisation),允许库重新使用存储,并使用旧指针访问存储;
l 字节类型:新的类型byte在<cstddef>中定义(不在<stddef.h>,并且只定义在命名空间std中),它和unsigned char具有相同的布局,和现有的字符类型一样允许别名(aliasing),并且定义了安位操作。
- 新的标准库特性
l 数学特殊函数:这些函数只添加到<cmath>,而没有添加到<math.h>,并且只定义在命名空间std中;
l 文件系统:文件系统技术规范(Filesystems Technical Specification)的内容现已加入C++。文件系统库允许以可移植的方式与目录和类似目录的结构进行交互。它主要以POSIX为模型,但它足够灵活,可以在各种系统上实现;
l 并行:并行技术规范(Parallelism Technical Specification)的内容现已加入C++。它为很多算法增加了重载,这些新的重载额外接收一个执行策略参数。支持三种执行策略,分别提供顺序(sequential)、并行(parallel)和向量化(vectorized)的执行。
l 新算法:并行技术规范为标准库添加了几种新算法,加入它们的动机是它们可以有效的并行执行,但也提供了通常的简单形式:for_each_n、reduce、transform_reduce、exclusive_scan、inclusive_scan、transform_ exclusive_scan、transform_nclusive_scan。注意,reduce看起来与现有的accumulated相似,但reduce不保证任何的操作顺序;
l 新算法sample:从一个范围里均匀选取最多n个元素作为样本;
l 新类型string_view:string_view(以及basic_string_view):API接口的推荐类型,如果API需要读取字符串的类容,但是不需要取得字符串的所有权或者修改字符串,它可以从char指针构造,但是其他的字符串类型应该自己提供到string_view的隐式转换;
l 新类型any:类型any对可复制的对象进行类型擦出,可以用any做的事基本上有以下三件:1.把T类型的值放入其中;2.复制它;3.检查它是否包含一个U类型的值,并且取出这个值,取出操作只有在U就是T的时候才会成功;
l 新的类模版variant:variant是一个可辨识联合,variant<A, B, C>类型的值在任何时间都包含一个类型A、B或者C之一的值;
l 新的类模版optional:一个可选的值,一个optional<T>表示一个T值,或者表示没有值(由类型nullopt_t标记),在某方面,可以认为它等同于variant<nullopt_t, T>,但是它具有专门的接口;
l invoke:以统一形式调用Callable实体(包括函数、函数对象和成员指针)的工具。这允许用户编写的库可以使用与标准的invoke规则相同的行为。is_invocable、is_ invocable_r、invoke_result可用于推断可调用行和调用结果的特性;
l 基本字符串转换:函数to_chars和from_chars分别生成和解析数字数字的字符串表示;
l 类型别名模版:void_t、bool_constant;
l 逻辑操作元函数:用于元编程的变长元函数conjunction、disjunction和negation。这些特性在元编程的意义上是短路的,不影响结果的模版不会被实例化;
l 用于SFINAE友好的swap特性:新的trait is_swappable、is_nothrow_swappable、is_ swappable_with、is_nothrow_swappable_with;
l 新trait:is_aggregate检查类型是否是聚合类;has_unique_object_representations判断特定的基于值的操作是否可以用基于对象表示的操作代替。
l 非成员函数size、data、empty:新曾的函数补充了现有的非成员函数begin、end等等。通过这些函数,可以用统一的方式访问标准容器和C风格数组;
l clamp:clamp(x, low, high)在x处于区间[low, high]内时返回x,否则返回最接近的边界;
l gcd和lcm:数论中的函数,计算两个整数的最大公约数和最小公倍数;
l shared_mutex类:读写互斥体,能够以共享或独占模式锁定;
l 干扰尺寸:两个新的实现定义常量hardware_constructive_interterence_size和hardware_destructive_interterence_size允许平台记录其高速缓存行大小,以便用户避免虚假共享并提高局部性;
l 元组apply:调用一个callable,参数从给定的元组中提取;
l 从元组构造:新的函数模版make_from_tuple,功能是用给定元组的成员初始化T类型的值,它有点像刚提到的apply,但它适用于构造函数;
l 通用否定函数对象not_fn:一个调用包装器,对它包装的callable取否定,它适用于具有任意数量参数callable,它取代了旧的not1和not2包装器;
l memory resource:一套新的组件,包括用于动态选择内存提供者的memory resource基类,以及三个具体实现synchronized_pool_resource、unsynchronized_pool_resource、monotonic_buffer_ resource;
l 搜索器函数对象:使用boyer-moore和boyer-moore-horspool算法,用于搜索子字符串的函数对象,和一个使用这些函数对象的算法。
- 现有特性的修改
l 简要的静态断言:static_assert声明不再需要第二个参数,如:static_assert(N > 0);
l 嵌套命名空间声明:如:使用namespace X::Y{…}代替namespace X{ namespace Y{…}};
l 许使用typename声明模版的模版参数;
l 基于范围的for循环接受不同的begin/end类型;
l using-declaration中的包扩展;
l 固定枚举值的构造:如 类型为固定枚举E的变量可以用E e{ 5 };的形式定义,不再需要啰嗦的E e { E(5) };
l 从花括号列表中推导auto的新规则:以前auto a{1, 2, 3}, b{1};是允许的,两个变量的类型都是initializer_list<int>,现在auto a{1, 2, 3};是错误的,auto b{1};声明一个int。注意,auto a = {1, 2, 3}, b = {1};保持不变,推导出initializer_list<int>。此改变预期作为C++14的缺陷解决方案;
l 对聚合初始化的扩展:列表初始化现在可以用聚合初始化的方式初始化基类子对象,例如,对于聚合类型struct base{ int a1, a2; }; struct derived : base{ int b1;}; 以下初始化现在是合法的:derived{{1,2}, 3}、derived{{ }, 3};
l uncaught_exceptions():函数uncaught_exception被弃用,新函数uncaught_exceptions返回计数而不是布尔值,以前的功能实际上是不能用的;
l 命名空间和枚举成员的属性:命名空间和枚举成员现在可以用属性标记;
l 属性命名空间不需要重复指定:简化了命名空间限定;
l 改进了std::map和std::unordered_map的插入注释,m.try_emplace(key, arg1, arg2, arg3)在m中已经含有key的时候没有任何效果,否则插入一个从参数构造的新元素;
l emplace的返回类型:顺序容器过去返回void的emplace、emplace_front、emplace_back成员函数模版,现在返回刚刚插入元素的引用;
l set和map拼接(splice):一个叫做节点句柄的新机制加入了标准容器库,这个新机制允许在不同的map/set对象之间移植元素,而不会触及容器中的对象。此外,这个机制使得提取出的键值进行可变访问成为可能;
l 非const的string::data:现在有了一个非const的basic_string::data重载,返回一个可变的指针;
l scoped_lock:变长版的lock_guard,它是一个变长的类模版scoped_lock<arg…>,可以同时给多个可锁的对象加锁,并且在析构函数中释放锁;
l atomic::is_always_lock_free:一个新的静态成员常量is_always_lock_free记录了给定原子类型的操作是否总是无锁的;
l 数组的share_ptr:类模版share_ptr现在可以支持C风格数组,只需传入T[]或T[N]作为模版参数。接收原始指针的构造函数将会设置合适的数组内存释放器;
l share_ptr::weak_type: share_ptr<T>现在有了一个成员类型weak_type,它是weak_ptr<T>的别名,这使得泛型代码不需要解构share_ptr的类型就可以知道对应的weak_ptr类型;
l 三维的斜边长:三维斜边长hypot(x, y, z)可以用来计算三维空间中两个点的距离,作为额外的重载加入<cmath>(没有加入<math.h>,并且只定义在命名空间std中);
l 更多用于未初始化内存的算法:增加在未初始化的内存中构造对象和销毁对象的算法,包括分别进行默认初始化和值初始化的版本;
l 内存分配器对不完整类型的支持:这项改变放宽了内存分配器对它的值类型的要求,使得值类型可以是不完整类型,如:允许递归结构,struct X{ std::vector<X> data; };
l 对<chrono>的改变:为时间点增加了向上取整(floor)、向下取整(ceiling)、除法(division)、和四舍六入五成双取整(rounding);
l char_traits的constexpr支持:对于标准要求的所有的char_traits特化,也就是std::char_traits<char>、std::char_traits<wchar_t>、std::char_traits<char16_t>、std::char_traits<char32_t>这四类,成员函数length、compare、find和assign现在都是constexpr成员函数了,这使得string::view可以在常量表达式中更广泛地使用;
l 改善pair和tuple:这个变化使得pair和tuple的构造函数变为“带条件的explicit”构造函数,只有在有某个元素的对应构造函数是explicit的时候,pair和tuple的构造函数才是explicit的;
l 对common_type改变;
- 其它杂项
l C++引用C11:C++标准现在正式的引用C11为“C标准”了。这不仅是对应ISO的要求,也使得我们可以使用aligned_alloc,它对于改进动态内存管理非常有用;
l 保留的命名空间:所有形如stdN(其中N是一串数字)的命名空间现在被保留了;
l C库总览:一个纯粹非技术性的变化,标准的“C库”部分的所有头文件的内容现在C++标准文档中以完整的总览的形式展现(也就是完整列出每个标准头文件包含的完整声明),而不再是像以前一样只列出名字;
l 术语forwarding reference、default memory initializer、templated entity、contiguous iterator:这些变化没有正式的影响,但是它们为迄今为止只从语言规则中出现的概念建立了官方术语。精确和众所周知的术语简化了关于C++的讨论,也简化了规范。
二、C++标准库
C++强大功能来源其丰富的类库和库函数,C++标准库的内容总共在50个标准的头文件中定义(不同C++标准中有所增减,以下所列为C++98标准库),其中18个提供了C库的功能。标准库的质量、效率和编程风格得到业界高度认可的。
C++标准库的所有头文件都没有扩展名,C++标准库以<cname>形式的标准头文件提供,在<cname>形式的标准头文件中,与宏相关的名称在全局作用域中定义,其它名称在std命名空间中声明。在C++中还可以使用name.h形式的标准C库头文件名,C++标准库内容主要分为10类:(最新内容请参考:https://zh.cppreference.com/w/cpp/header)
1.语言支持;
2.输入/输出;
3.诊断;
4.一般工具;
5.字符串;
6.容器;
7.迭代器;
8.算法;
9.数值操作;
10.本地化;
1. 语言支持
<cstddef>定义宏NULL和offsetof,以及其它标准类型size_t和ptrdiff_t。与对应的标准C头文件的区别是,NULL是C++空指针常量的补充定义,宏offsetof接受结构或者联合类型参数,只要他们没有成员指针类型的非静态成员即可。
<limits>提供与基本数据类型相关的定义,例如,对于每个数值数据类型,它定义了可以表示出来的最大值和最小值以及二进制数字的位数。
<climits>提供与基本整数数据类型相关的C样式定义,这些信息的C++样式定义在<limits>中。
<cfloat>提供与基本浮点数据类型相关的C样式定义,这些信息的C++样式定义在<limits>中。
<cstdlib>提供支持程序启动和终止的宏和函数,这个头文件还声明了许多其它杂项函数,如搜索和排序函数,从字符串转换为数值等函数。它与对应的标准C头文件stdlib.h不同,定义了abort(),abort()函数还有额外的功能,它不为静态或自动对象调用析构函数,也不调用传给atexit()函数的函数;它还定义了exit()函数的额外功能,可以释放静态对象,以注册的逆序调用atexit()注册的函数,清除并关闭所有打开的C流,把控制权返回给主机环境。
<new>支持动态内存分配。
<typeinfo>支持变量在运行期间的类型标识。
<exception>支持异常处理,这是处理程序中可能发生的错误的一种方式。
<sctdarg>支持接收数量可变的参数的函数,及在调用函数时,可以给函数传递数量不等的参数。它定义了宏va_arg、va_end、va_start以及va_list类型。
<csetjmp>为C样式的非本地跳跃提供函数,这些函数在C++中不常用。
<csignal>中断处理提供C样式支持。
2. 流输入/输出
<ios>定义iostream的基类。
<istream>为管理输出流缓存区的输入定义模版类。
<ostream>为管理输出流缓存区的输出定义模版类。
<iostream>支持标准流cin、cout、cerr和clog的输入与输出,它还支持多字节字符标准流wcin、wcout、wcerr和wclog。
<iomanip>提供操作程序,允许改变流的状态,从而改变输出的格式。
<sstream>支持字符串的流输入输出。
<fstream>支持文件的流输入输出。
<streambuf>支持流输入输出的缓存。
<iosfwd>为输入输出对象提供向前的声明。
<cstdio>为标准流提供C样式的输入和输出。
<cwchar>支持多字节字符的C样式输入和输出。
3. 诊断
<stdexcept>定义标准异常,提供处理错误方式。
<cassert>定义断言宏,用于检查运行期间的情形。
<cerror>支持C样式的错误信息。
4. 一般工具
<utility>定义重载的关系运算符,简化关系运算符的写入,它还定义了pair类型,该类型是一种模版类型,可以存储一对值,这些功能在库的其它地方使用。
<functional>定义了许多函数对象模型和支持函数对象的功能,函数对象是支持operator()()函数调用运算符的任意对象。
<memory>给容器、管理内存的函数和auto_ptr模版类定义标准内存分配器。
<ctime>支持系统时钟函数。
5. 字符串
<string>为字符串类型提供支持和定义,包括单字节字符串(char)的string和多字节字符串(wchar_t)的string。
<cctype>单字节字符类别。
<cwctype>多字节字符类别。
<cstring>为处理非空字节序列和内存块提供函数。这不同于对应的标准C库头文件,几个C样式字符串的一般C库函数被返回值为const和非const的函数代替了。
<cwchar>为处理执行I/O和转移多字节字符序列提供函数,这不同于对应的标准C库头文件,几个多字节C样式字符串操作的一般C库函数被返回值为const和非const的函数代替了。
<stdlib>为把单字节字符串转换为数值、在多字节字符和多字节字符串之间转换提供函数。
6. 容器
<vector>定义vector序列模版,这是一个大小可以重新设置的数组类型,比普通数组更安全灵活。
<list>定义list序列模版,这是一个序列的链表,常用于频繁在任意位置插入和删除元素。
<duque>定义duque序列模版,支持在开始和结尾高效的插入和删除操作。
<queue>为队列(先进先出)数据结构定义序列适配器queue和priority_queue。
<stack>为堆栈(后进先出)数据结构定义序列适配器stack。
<map>关联容器类型,允许根据键值是唯一的,且按照升序存储,multimap键可以不唯一。
<set>关联容器类型,升序方式存储唯一值,multiset值可以不唯一。
<bitset>为固定长度的位序列定义bitset模版。
7. 迭代器
<iterator>给迭代器提供定义和支持。
8. 算法
<algorithm>提供一组基于算法的函数,包括置换、排序、合并和搜索。
<stdlib>声明C标准库函数bsearch()和qsort(),进行排序和搜索。
<ciso646>允许在代码中使用and代替&&。
9. 数值操作
<complex>支持复杂数值的定义和操作。
<valarray>支持数值矢量的操作。
<numeric>在数值序列上定义一组一般数学操作,例如,accumulated和inner_product。
<cmath>支持C数学库,还增加了重载函数,以支持C++约定。
<cstdlib>提供的函数可以提取整数的绝对值,对整数进行取余操作等。
10. 本地化
<locale>提供的本地化包括字符类别、排序序列以及货币和日期表示。
<clocale>对本地化提供C样式支持。
三、C标准库
C标准库是一组C内置函数、常量和头文件(参考:https://zh.cppreference.com/w/c/heade)
<assert.h> 条件编译宏,将参数与零比较;
<complex.h>(C99起) 复数运算;
<ctype.h> 用来确定包含于字符数据中的类型的函数;
<error.h> 报告错误条件的宏;
<fenv.h>(C99起) 浮点数环境;
<float.h> 浮点数类型的极限;
<inttypes.h>(C99起) 整数类型的格式转换;
<iso646.h>(C99起) 符号的替代写法;
<limits.h> 本地类型的大小;
<locale.h> 本地化工具;
<math.h> 常用数学函数;
<setjmp.h> 非局部跳转;
<signal.h> 信号处理;
<stdalign.h>(C11起) alignas与alignof便利宏;
<stdarg.h> 可变参数;
<stdatomic.h>(C11起) 原子类型;
<stdbool.h>(C99起) 布尔类型;
<stddef.h> 常用宏定义;
<stdint.h>(C11起)定宽整数类型;
<stdio.h> 输入/输出;
<stdlib.h> 基础工具:内存管理、程序工具、字符串转换、随机数;
<stdnoreturn.h>(C11起) noreturn便利宏;
<string.h> 字符串处理;
<tgmath.h>(C99起) 泛型数学(包装math.h和complex.h的宏);
<threads.h>(C11起) 线程库;
<time.h> 时间/日期工具;
<uchar.h>(C11起) UTF-16和UTF-32字符工具;
<wchar.h>(C95起) 扩展多字节和款字节工具;
<wctype.h>(C95起) 用来确定包含于宽字符数据中的类型的函数。
四、STL标准模版库
STL(Standard Template Library,标准模版库)前生是惠普实验室开发的一系列软件的统称。现在主要出现在C++中,在被引入C++标准之前该技术就已经存在了很长的一段时间,STL是C++标准库中的一个子集,这个庞大的子集占据了整个库的大约80%的分量。
STL代码从广义上讲分为三类:algorithm(算法)、container(容器)、iterator(迭代器),几乎所有的代码都采用了模版类和模版函数的方式,相对于传统的由函数和类组成的库来说提供了更好的代码重用机会。在C++标准中,STL被组织为下面13个头文件:< algorithm >、<numeric>、<functional>、<vector>、<list>、<map>、<set>、<deque>、<queue>、<stack>、<iterator>、<memory>和<utility>。
1. Algorithm(算法)
STL提供了大约100个实现算法的模版函数,算法部分主要头文件包含< algorithm >、<numeric>和<functional>。< algorithm >是所有STL头文件中最大的一个,由一大堆模版函数组成,每个函数在很大程度上都是独立的,其中常用到的算法涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等;<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模版函数,包括加法和乘法在序列上的一些操作;<functional>中则定义了一些模版类,用已声明函数对象。
2. Container(容器)
容器部分主要由头文件<vector>、<list>、<map>、<set>、<deque>、<queue>和<stack>组成,对于常用的一些容器和容器适配器,STL提供了三种容器适配器:stack、queue、priority_queue。
3. Iterator(迭代器)
迭代器在STL中用来将算法和容器联系起来,起着一种黏合剂的作用,几乎STL提供的所有算法都是通过迭代器存取元素序列进行工作的,每一个容器都定义了其本身所专有的迭代器,用以存取容器中的元素。
迭代器部分主要由头文件<iterator>、<memory>和<utility>组成。<utility>是一个很小的头文件,它包括了贯穿使用在STL中的几个模版的声明;<iterator>中提供了迭代器使用的许多方法,而对于<memory>的描叙则十分困难,它以不同寻常的方式为容器中的元素分配存储空间,同时也为某些算法执行期间产生的临时对象提供机制;<memory>中主要部分是模版类allocator,它负责产生所有容器中的默认分配器。
五、小结
关于C++的学习路线,本人也是在长期的摸索中,C++之强大,令人折服,期初从事C++方向的工作也正因此。建议读者先从基本功做起,了解C/C++语法规则,推荐《C++ primer》一书,一定要打好基础,掌握好基本理论知识,正所谓:基础不牢,地动山摇。基础不好,后面学其他深一点的东西,也是云里雾里,过眼烟云,转眼就忘。基本功做好后,有时间可以多练练手,在实践中辨真知。其次,学习C++优点,如何编写出高质量高性能的程序。故善用兵者,避其锐气,击其惰归,这里道理一样,择优避缺,推荐《More Effective C++》一书,里面例举了大量在实践中可优化的方法,哪些值得做,哪些你需要避免。另外,对于工程性的了解,在此阶段也可以进行同步学习,推荐《代码大全》,此书无关语言,主要讲解工程性的东西和编码惯用的一些规则和约束。到这里,其实你已经很厉害了,平时开发基本够用,如果不想浅尝辄止,下面可以学习一些进阶书籍,了解大神如何操作的,如《Effective STL》、《Thinking in C++》,建议读者慢慢品读。
参考网址:
https://www.iso.org/standard
https://www.open-std.org
https://zh.cppreference.com
作者:博客园博主 KeepHopes,对大数据、人工智能领域颇感兴趣,请多多赐教!
原文链接:https://www.cnblogs.com/yuwanxian/articles/10890676.html
版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议。转载请注明出处,谢谢!

浙公网安备 33010602011771号