C++11标准库(第二版)笔记整理

1.C++编译环境的组成:

img

  • C语言兼容库:头文件带.h,是C++编译器提供商为推广自己的产品,而提供的C兼容库不是C++标准库提供的),内置的C库
  • C++标准库:如string cstdio(注意不带.h)是C++标准库提供的。使用时要用using namespace std
  • 编译器扩展库:这是针对不同的编译器而独有扩展,例如g++和vc++,他们在这一板块就不同。
  • C++标准库语法模块:C++标准语法的支持
  • C++扩展语法模块:同样是针对不同的编译器而独有的扩展语法

2.C++标准库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2lveYxw-1646271445999)(F:\C++\C++库\image-20220301092740399.png)]

(1)流输入/输出

iostream:支持标准流cin、cout、cerr和clog的输入和输出,还支持多字节字符标准流wcin、wcout、wcerr和wclog。
iomanip:提供操纵程序,允许改变流的状态,从而改变输出的格式。
ios:定义iostream的基类。
istream:为管理输出流缓存区的输入定义模板类。
ostream:为管理输出流缓存区的输出定义模板类。
sstream:支持字符串的流输入输出。
fstream:支持文件的流输入输出。
iosfwd:为输入输出对象提供向前的声明。
streambuf:支持流输入和输出的缓存。
cstdio:为标准流提供C样式的输入和输出。
cwchar:支持多字节字符的C样式输入输出。
(2)数值操作

complex:支持复杂数值的定义和操作。
valarray:支持数值矢量的操作。
numeric:在数值序列上定义一组一般数学操作,例如accumulate和inner_product。
cmath:这是C数学库,其中还附加了重载函数,以支持C++约定。
cstdlib:提供的函数可以提取整数的绝对值,对整数进行取余数操作
(3)诊断功能

stdexcept:定义标准异常。
cassert:定义断言宏,用于运行时检查。
cerrno:支持C样式的错误信息

(4)语言支持功能

cstddef:定义宏NULL和offsetof以及其它标准类型size_t和ptrdiff_t。与对应的标准C头文件的区别是,NULL是C++空指针常量的补充定义(C++11中已有关键字nullptr),宏offsetof接受结构或者联合类型参数,只要没有成员指针类型的非静态成员即可。
limits:提供与基本数据类型相关的定义。例如,对于每个数值数据类型,它定义了可以表示出来的最大值和最小值以及二进制数字的位数。
climits:提供与基本整数数据类型相关的C样式定义,C++样式定义在中。
:提供与基本浮点型数据类型相关的C样式定义,C++样式定义在limits中。
cstdlib:提供支持程序启动和终止的宏和函数,还声明了许多其他杂项函数,例如搜索和排序函数,从字符串转换为数值等函数。cstdlib与对应的标准C头文件stdlib.h不同,定义了abort(void)。abort()函数还有额外的功能,它不为静态或自动对象调用析构函数,也不调用传给atexit()函数的函数。它还定义了exit()函数的额外功能,可以释放静态对象,以注册的逆序调用用atexit()注册的函数。清除并关闭所有打开的C流,把控制权返回给主机环境。
new:支持动态内存分配。
typeinfo:支持变量在运行期间的类型标识。
exception:支持异常处理,是处理程序中可能发生的错误的一种方式。
cstdarg:支持接受数量可变的参数的函数。即在调用函数时,可以给函数传送数量不等的数据项。定义了宏va_arg、va_end、va_start以及va_list类型。
csetjmp:为C样式的非本地跳跃提供函数,在C++中不常用。
csignal:为中断处理提供C样式支持。
(5)字符串处理

string:为字符串类型提供支持和定义,包括单字节字符串(由char组成)的string和多字节字符串(由wchar_t组成)。
cctype:单字节字符类别。
cwctype:多字节字符类别。
cstring:为处理非空字节序列和内存块提供函数。不同于对应的标准C库头文件,C样式字符串的一般C库函数被返回值为const和非const的函数对替代。
cwchar:为处理、执行I/O和转换多字节字符序列提供函数,不同于对应的标准C库头文件,几个多字节C样式字符串操作的一般C库函数被返回值为const和非const的函数对替代。
cstdlib:为把单字节字符串转换为数值、在多字节字符和多字节字符串之间转换提供函数。

(6)容器类模板

vector:定义vector序列模板,是一个大小可以重新设置的数组类型,比普通数组更安全、更灵活。
list:定义list序列模板,是一个序列的链表,常常在任意位置插入和删除元素。
deque:定义deque序列模板,支持在开始和结尾的高效插入和删除操作。
queue:为队列(先进先出)数据结构定义序列适配器queue和priority_queue。
stack:为堆栈(后进先出)数据结构定义序列适配器stack。

map: map是一个关联容器类型,允许根据键值是唯一的,且按照升序存储。multimap类似于map,但键不是唯一的。

set:set是一个关联容器类型,用于以升序方式存储唯一值。multiset类似于set,但是值不必是唯一的。
bitset:为固定长度的位序列定义bitset模板,它可以看作固定长度的紧凑型bool数组。
array:(TR1)固定大小数组,支持复制。
forward_list:(c++11)单向列表,支持快速随机访问。
unordered_set:(TR1)无序容器set,其元素随机存放。multiset类似于set,但是值不必是唯一的。
unordered_map:(TR1)无序容器map,其键值随机存放。multimap类似于map,但键不是唯一的

(7)迭代器

iterator:给迭代器提供定义和支持

(8)算法

algorithm:提供一组基于算法的函数,包括置换、排序、合并和搜索。
cstdlib:声明C标准库函数bsearch()和qsort(),进行搜索和排序。
ciso646:允许在代码中使用and代替&&

3.C++标准库

C++标准库可以分为两部分:

  • 标准函数库:这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自C语言
  • 面向对象类库:这个库是类及其相关函数的集合

C++标准库包含了所有的C标准库,为了支持类型安全,做了一定的添加和修改。

标准函数库:

标准函数库分为以下几类:输入/输出IO 、字符串和字符处理、数学、时间 日期和本地化、动态分配、其他、宽字符函数

面向对象类库:

标准的C++面向对象类库定义了大量支持一些常见操作的类,比如输入/输出I/O、字符串处理、数值处理。面向对象类库包括以下内容:

标准的C++ I/O类、String类、数值类、STL容器类、STL算法、STL函数对象、STL迭代器、STL分配器、本地化库、异常处理类、杂项支持库

第3章 语言新特性

3.1 C++11语言新特性

1.微小但重要的语法提升

Template表达式内的空格

“在两个template表达式的闭符之间放一个空格”的要求已经过时了:

vector<list<int> >;			//OK in each C++ version
vector<list<int>>;			//OK since C++11

nullptr和std::nullptr_t

C++11允许你使用nullptr取代0或NULL,用来表示一个pointer指向所谓的no value(此不同于拥有一个不确定值)。这个新特性特别能够帮助你在“null pointer被解释为一个整数值”时避免误解。

void f(int);
void f(void*);
f(0);        //calls f(int)
f(NULL);    //calls f(int) if NULL is 0,ambiguous otherwise
f(nullptr);//calls f(void*)

nullptr是个新关键字。它被自动转换为各种pointer类型,但不会被转换为任何整数类型。

2.以auto完成类型自动推导

C++11允许你声明一个变量或对象(object)不需要指明其类型,只需说它是auto

auto i = 42;		//i has type int
double f();
auto d = f();		//d has type double

以auto声明的变量,其类型会根据其初值被自动推导出来,因此一定需要一个初始化操作:

auto i ;			//ERROR:can't deduce the type of i

可为它加上额外的限定符:

static auto var = 0.19;

如果类型很长或表达式很复杂,auto特别有用:

vector<string> v;
auto pos = v.begin();		//pos ha type vector<string>::iterator
auto lam = [](int x) -> bool {	//lam has the type of a lambda
    ...,					//taking an int and returning a bool
};

3.一致性初始化(Uniform Initializaion)与初值列(Initializer List)

4.Range-Based for循环

C++11引入一个崭新的for循环形式,可以逐一迭代某个给定的区间、数组、集合内的每一个元素。

一般性语法:

for(decl : coll){
    statement
}
for(int i: {1,3,5,7,9,11.13}){
    cout<<i<<endl;
}

如果要将vector vec的每个元素elem乘以3:

vector<double> vec;
for( auto &elem : vec){
    elem *= 3;
    cout<<elem<<endl;
}

5.Move语义和Rvalue Reference

C++11的一个重要的特性就是,支持move semantic(搬迁语义)。这项特性更进一步进入了C++主要涉及目标内,用以避免非必要拷贝(copy)和临时对象(temporary)。

新特性的出现是为了解决现有的问题或不足之处,move的出现为了解决某些场景下深拷贝的效率问题。

6.关键字noexcept

C++11提供了关键字noexcept,用来指明某个函数无法—或不打算—抛出异常

void foo() noexcept;		//声明了foo()不打算抛出异常。

若有异常未在foo()内被处理—亦即如果foo()抛出异常—程序会被终止,然后std::terminate()被调用并默认调用std::abort()

你甚至可以指明在某种条件下函数不抛出异常。

void swap(Type& x,Type& y) noexcept(noexcept(x.swap(y)))
{
    x.swap(y);
}

在noexcept()中你可以指定一个Boolean条件,若符号就抛出异常

7.关键字constexpr

constexpr常量表达式,常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候。

自C++11起,constexpr可用来让表达式核定于编译器

constexpr int square(int x)
{
	return x*x;
}

constexpr表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。声明为constexpr的变量一定是一个const变量,而且必须用常量表达式初始化

8.崭新的Template特性

Variadic Template:自C++11起,template可拥有那种“得以接受个数不定之template实参”的参数。此能力称为variadic template.

void print()
{

}
template<typename T,typename... Types>
void print(const T& firstArg,const Types&... args)
{
    cout<<firstArg<<endl;   //print first argument
    print(args...);         //call print() for remaining arguments

}

void test01()
{
    print(7.5,"hello",bitset<16>(32),42);
}

9.Alias Template(带别名的模板,或者叫Template Typedef)

自C++11起,支持template(partial) type definiation

template <typename T>

using Vec = vector<T,MyAlloc<T>>;	//standard vector using own allocator
Vec<int> coll;
// 等价于
vector<int,MyAlloc<int>> coll;

10.Lambda

int x = 0;
int y = 42;
auto qqq = [x,&y]{
    cout<<"x: "<<x<<endl;
    cout<<"y: "<<y<<endl;
    ++y;    //OK
};
x = y = 77;
qqq();
qqq();
cout<<"final y: "<<y<<endl;
int id = 0;
auto f = [id]() mutable{
    cout<<"id:"<<id<<endl;
   	++id;       //OK
};
id = 42;
f();
f();
f();
cout<<id<<endl;

//可以把上述lambda的行为视同下面这个function object
class {
private:
    int id;      //copy of outside id
public:
     void operator()(){
         cout<<"id:"<<id<<endl;
         ++id;   //OK
     }
};

11.关键字decltype

decltype类型说明符,它的作用是选择返回操作数的数据类型,它的出现主要是解决复杂的类型声明。decltype并不会实际计算表达式的值,编译器分析表达式并得到它的类型。

//sum的类型是函数f返回的类型
decltype(f()) sum = x;

3.2 虽旧犹新的语言特性

Default Template Parameter(模板参数默认值)

Class template可以拥有默认实参。例如下面的声明式允许我们在声明class MyClass对象时指定1或2个template实参。

template<typename T,typename container = vector<T>>
class MyClass;

如果你只传入一个实参,第二实参会采用默认值:

MyClass<int> x1;//equivalent to:MyClass<int,vector<int>>

第4章 一般概念

4.1 命名空间Namespace std

当你采用不同的模板或程序库时,经常会出现名称冲突现象,这是因为不同的模板和程序库可能对不同的对象使用相同的标识符(identifier)。Namespace正是用来解决这个问题的。所谓Namespace是指标识符的某种可见范围。

4.4 Callable Object(可被调用的对象)

Callable Object“可被某种方式调用其某些函数”的对象。它可以是:

  • 一个函数,接受额外传入的args作为实参(argument)
  • 一个指向成员函数的指针(a pointer to a member function),当你通过对象调用它,该对象被传递称为第一个实参(必须是个reference或pointer),其他实参则一一对应成员函数的实参。
  • 一个函数对象(function object,该对象拥有operator()),附带的args被传递作为实参。
  • 一个lambda,严格地说它是一种函数对象
void func(int x,int y);
auto l = [](int x,int y){

};
class C{
    public:
        void operator()(int x,int y) const;
        void memfunc(int x,int y) const;
};

void test01()
{
    C c;
    shared_ptr<C> sp(new C);
    //bind() use callable objects to bind arguments
    bind(func,77,33)();
    bind(l,77,33)();
    bind(C(),77,33)();
    bind(&C::memfunc,c,77,33)();
    bind(&C::memfunc,sp,77,33)();
}

第5章 通用工具

本章讲解C++标准库的通用工具,这些工具包括:

  • class pair<>和class tuple<>
  • Smart pointer class(shared_ptr()和unique_ptr)
  • 数值极值(Numeric limit)
  • Type trait和type utility
  • 辅助函数(如min()、max()和swap())
  • class ratio<>
  • Clock和timer

5.1 Pair和Tuple

5.1.1 Pair

class pair可将两个value视为一个单元。C++标准库内多处用到了这个class。尤其容器map、multimap、unordered_map和unordered_multimap就是使用pair来管理其以ke/value pair形式存在的元素。任何函数如果需返回两个value,也需要用到pair

Struct pair定义于 提供了first_type和second_type类型定义式,用来表示第一value和第二value的类型。

元素访问:

//generic output operator for pairs(limited solution)
template<typename T1,typename T2>
ostream& operator << (ostream& strm,const pair<T1,T2>& p)
{
    return strm<<"["<<p.first<<","<<p.second<<"]";
}

typedef pair<int,float> IntFloatPair;
IntFloatPair p(42,3.14);
//访问元素
cout<<get<0>(p)<<endl;
cout<<get<1>(p)<<endl;
cout<<p.first<<endl;
cout<<p.second<<endl;

便捷函数make_pair():返回一个pair对

Template函数make_pair()使你无需写出类型就能生成一个pair对象

不必这样写:pair<int,char>(42,’@’)

可写成这样:make_pair(42,’@’)

5.1.2 Tuple(不定数的值组)

Tuple是TR1引入的东西,它扩展了pair的概念,拥有任意数量的元素。

C++11中variadic template被引入进来,使template得以接受任何数量的template实参。出现在中的class tuple声明式现在被简化如下:

namespace std{
    template<typename... Types>
    class type;
}

Tuple的操作:

  • 使用便捷函数make_tuple(),创建一个tuple
  • 通过get<>() function template,可以访问tuple的元素
//create a four-element tuple
    tuple<string,int,int,complex<double>> t;
    //create and initialize a tuple explicitly
    tuple<int,float,string> t1(41,6.3,"nico");

    cout<<get<0>(t1)<<" ";
    cout<<get<1>(t1)<<" ";
    cout<<get<2>(t1)<<" ";
    cout<<endl;

    //create tuple with make_tuple()
    auto t2 = make_tuple(66,44,"nico");

    //assign second value in t2 to t1
    get<1>(t1) = get<1>(t2);

    //comparison and assignment
    if(t1<t2){      //compares value for value
        t1 = t2;    //OK,assigns value for value
    }

    cout<<get<0>(t1)<<" ";
    cout<<get<1>(t1)<<" ";
    cout<<get<2>(t1)<<" ";
    cout<<endl;

5.2 Smart Pointer(智能指针)

  • shared_ptr 实现共享式拥有(shared ownership)。多个smart pointer可以指向相同对象,该对象和其相关资源会在“最后一个reference被销毁”时被释放。
  • unique_ptr 实现独占式拥有(exclusive ownership)或严格拥有(strict ownership),保证同一时间内只有一个smart pointer可以指向该对象。你可以以交拥有权。它对于避免资源泄露(resource leak)—例如,“以new创建对象后因为发生异常而忘记调用delete”----特别有用

5.2.1 class shared_ptr

对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过make_shared函数或者通过构造函数传入普通指针,可以通过get函数获得普通指针。

使用shared_ptr:

#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

int main()
{
    //two shared pointers representing two persons by theirf name
    shared_ptr<string> pNico(new string("nico"));
    shared_ptr<string> PJutta(new string("jutta"));
    
    //capitalize person names
    (*pNico)[0] = 'N';
    PJutta->replace(0,1,"J");

    //put them multiple times in a container
    vector<shared_ptr<string>> whoMadeCoffee;
    whoMadeCoffee.push_back(PJutta);
    whoMadeCoffee.push_back(PJutta);
    whoMadeCoffee.push_back(pNico);
    whoMadeCoffee.push_back(PJutta);
    whoMadeCoffee.push_back(pNico);

    //print all elements
    for(auto ptr : whoMadeCoffee){
        cout<<*ptr<<" ";
    }
    cout<<endl;

    //overwrite a name again
    *pNico = "Nicolai";

    //print all elements
    for(auto ptr : whoMadeCoffee){
        cout<<*ptr<<" ";
    }
    cout<<endl;

    //print some internal data
    cout<<"use_count:"<<whoMadeCoffee[0].use_count()<<endl;

    return 0;

}

在某些情况下,有些行为无法运作或不被期望。如循环指向,如果两对象使用shared_ptr互相指向对方,而一旦不存在其他reference指向它们时,想要释放它们和其对应资源。这种情况下shared_ptr不会释放数据,因为每个对象的use_count()扔是1.

标准库提供了weak_ptr,允许你“共享但不拥有”某对象。这个类会建立起一个shared pointer。一旦最末一个拥有该对象的shared pointer失去了拥有权,任何weak pointer都会自动成空。因此,在default和copy构造函数之外,weak_ptr只提供“接受一个shared_ptr”的构造函数。

5.2.2 unique_ptr

unique_ptr可确保一个对象和其相应的资源同一时间只被一个pointer拥有。一旦拥有者被销毁或变成empty,或开始拥有另一个对象,先拥有的那个对象就会被销毁,其任何相应资源也会被释放。

5.3 Type Trait和Type Utility

所谓type trait,提供一种用来处理type属性的办法。它是个template,可在编译器根据一个或多个template实参(通常也是type)产出一个type或value。

5.4 辅助函数

#include

minmax()返回一个pair<>,其中的first是最小值,second是最大值。

那些接受两个值的版本,返回的是个reference

swap函数:其泛化实现定义于

namespace std{
    template <typename T>
    inline void swap(T& a,T& b){
        T tmp(move(a));
        a = move(b);
        b = move(a);
    }
}

在其内部,数值被moved或被move assigned。

swap()的最大优势在于,通过模板特化或函数重载,我们可以为更复杂的类型提供特殊实现版本;这些特殊实现有可能交换内部成员,而非对对象赋值,这无疑大大节省了空间。标准库的所有容器和string都运用了这个技术。

注:C++11标准库(第二版)这本书长达1000多页,后面章节由于时间原因,没有做笔记整理。

用来处理type属性的办法。它是个template,可在编译器根据一个或多个template实参(通常也是type)产出一个type或value。

5.4 辅助函数

#include

minmax()返回一个pair<>,其中的first是最小值,second是最大值。

那些接受两个值的版本,返回的是个reference

swap函数:其泛化实现定义于

namespace std{
    template <typename T>
    inline void swap(T& a,T& b){
        T tmp(move(a));
        a = move(b);
        b = move(a);
    }
}

在其内部,数值被moved或被move assigned。

swap()的最大优势在于,通过模板特化或函数重载,我们可以为更复杂的类型提供特殊实现版本;这些特殊实现有可能交换内部成员,而非对对象赋值,这无疑大大节省了空间。标准库的所有容器和string都运用了这个技术。

注:C++11标准库(第二版)这本书长达1000多页,后面章节由于时间原因,没有做笔记整理。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值