Boost程序库完全开发指南:1.1-C++基础知识点梳理

发布时间 2023-10-05 01:57:35作者: 扫地升

  主要整理了N多年前(2010年)学习C++的时候开始总结的知识点,好长时间不写C++代码了,现在LLM量化和推理需要重新学习C++编程,看来出来混迟早要还的。

1.shared_ptr
解析:shared_ptr是一种计数指针,当引用计数变为0时,shared_ptr所指向的对象将会被删除。如下所示:

void test() {
    shared_ptr p1(new int); // 计数为1
    {
        shared_ptr p2(p1); // 计数为2
            {
                shared_ptr p2(p1); // 计数为3
            } // 计数为2
        } // 计数为1
} // 计数为0,同时int对象被删除

2.unique_ptr
解析:unique_ptr是定义在中的智能指针(smart pointer)。它持有对对象的独有权,即两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作。

3.const类成员函数
解析:const类成员函数不能修改任何成员变量,但是mutable修饰的变量除外。
说明:const int *p与int const *p没有区别;const int *p; (p可以修改,但是p指向对象的内容不可修改);int * const p; (p不可修改,但是p指向对象的内容可以修改)。

4.拷贝构造函数
解析:拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。在C++中,三种对象需要调用拷贝构造函数的情况,如下所示:
(1)对象以值传递的方式传入函数参数。
(2)对象以值传递的方式从函数返回。
(3)对象需要通过另外一个对象进行初始化。
说明:浅拷贝指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的是浅拷贝。大多情况下“浅拷贝”都能很好地工作,但是一旦对象存在了动态成员,那么浅拷贝就会出现问题。

5.《C++标准程序库》
解析:
(1)第1章至第4章总体介绍了本书及C++标准程序库;
(2)第5章至第9章分别从各个方面描述STL;
(3)第10章至第12章描述了一些“简单的”标准类别;
(4)第13章至第14章的主题是I/O和国际化;
(5)第15章描述C++标准程序库中内存模型的概念。
(6)附录主要是参考资料。

6.模板类ostream_iterator
解析:template <class T, class charT=char, class traits=char_traits<charT> > class ostream_iterator;。举个例子,如下所示:

// ostream_iterator example
#include <iostream>     // std::cout
#include <iterator>     // std::ostream_iterator
#include <vector>       // std::vector
#include <algorithm>    // std::copy
 
int main () {
  std::vector<int> myvector;
  for (int i=1; i<10; ++i) myvector.push_back(i*10);
 
  std::ostream_iterator<int> out_it (std::cout,", ");
  std::copy ( myvector.begin(), myvector.end(), out_it );
  return 0;
}

7.int* p和int *p区别
解析:没有区别,只不过int* p强调类型是int指针,而int *p强调对象是int指针。

8.extern语法
解析:
(1)extern修饰变量的声明
比如,extern int i。
(2)extern修饰函数的声明
比如,extern int fun(int i)。
(3)extern修饰C/C++函数的调用规范
比如,在C++中调用C库函数,需要在C++中用extern "C"声明要引用的函数。

9.#pragma once
解析:#pragma once是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次。需要注意的是这种方式是微软编译器独有的,并且不支持跨平台。如果需要支持跨平台,那么需要使用#ifndef/#define/#endif。

10.C++中的Virtual关键字
解析:
(1)virtual ReturnType Function_1(); //虚函数声明
(2)virtual ReturnType Function_2() = 0; //纯虚函数声明
说明:包含纯虚函数的类被称为抽象基类。

11.C++关键字
解析:

12.wchar_t(宽字符类型,双字节类型)
解析:wchar_t的本质是typedef unsigned short wchar_t;(重点理解char,wchar_t,string,wstring类型之间的相互转换)。
说明:wstring是宽char,Unicode编码,一个字符占两个字节大小;而string是窄char,ASCII编码,一个字符占一个字节大小。
说明:short int(2个字节);long int(4个字节);long double(8个字节)。要学会使用sizeof(wchar_t)查看数据类型的字节大小。

13.C++中的左值和右值
解析:
(1)左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
(2)右值(rvalue):指的是存储在内存中某些地址的数值。右值可以出现在赋值号的右边,但不能出现在赋值号的左边。

14.C++全局变量初始值
解析:
(1)int:0
(2)char:'\0'
(3)float:0
(4)double:0
(5)pointer:NULL
说明:当定义局部变量时,系统不会对其进行初始化,你必须自行对其进行初始化。

15.C++内存区域划分
解析:
(1)栈:由编译器自动分配和释放,通过存储的变量是局部变量、函数参数等。
(2)堆:由new分配的内存块,通常一个new对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
(3)自由存储区:由malloc等分配的内存块,用free释放掉内存块。
(4)全局/静态存储区:全局变量和静态变量共同占用同一块内存区。
(5)常量存储区:存储常量,不能修改。

16.C++类型限定符
解析:
(1)const:const类型的对象在程序执行期间不能被修改改变。
(2)volatile:修饰符volatile告诉编译器不对代码进行任何优化。
(3)restrict:restrict修饰的指针是能够访问所指区域的唯一入口。(C99新增)

17.C++存储类
解析:
(1)auto存储类:所有局部变量默认的存储类。
(2)register存储类:定义存储在寄存器中而不是RAM中的局部变量。
(3)static存储类:局部变量;全局变量;类数据成员变量。
(4)extern存储类:提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
(5)mutable存储类:如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。如果需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。

18.C++字符串
解析:
(1)C风格字符串:头文件#include ,常用的函数包括strcpy(s1, s2);strcat(s1, s2);strlen(s1);strcmp(s1, s2);strchr(s1, ch);strstr(s1, s2)。
(2)C++风格字符串:头文件#include
说明:C++运算符:算术运算符;关系运算符;逻辑运算符;位运算符;赋值运算符;杂项运算符。

19.C++继承与权限
解析:
(1)public => public继承 => public。
(2)public => protected继承 => protected。
(3)public => private继承 => private。
(4)protected => public继承 => protected。
(5)protected => protected继承 => protected。
(6)protected => private继承 => private。
(7)private => public继承 => 子类无权访问。
(8)private => protected继承 => 子类无权访问。
(9)private => private继承 => 子类无权访问。
说明:成员和类的默认访问修饰符是private。

20.友元函数和友元类
解析:
(1)友元函数
类的友元函数可以访问类的所有私有(private)成员和保护(protected)成员,但是友元函数并不是类的成员函数。比如, friend void printWidth( Box box );
(2)友元类
友元类及其所有成员都是友元。比如friend class ClassTwo;

21.stringstream
解析:标准头文件定义了一个叫做stringstream的类,可以进行字符串与数值之间的相互转换。如下所示:

string mystr ("1204");
int myint;
stringstream(mystr) >> myint;

说明:命令执行完毕后,变量myint存储的数值为1204。

22.字符串和其它数据类型的转换
解析:函数库cstdlib提供了3个有用的函数。如下所示:
(1)atoi: 将字符串string转换为整型int。
(2)atol: 将字符串string转换为长整型long。
(3)atof: 将字符串string转换为浮点型float。

23.ANSI-C中的动态内存管理
解析:
(1)malloc函数:void *malloc(unsigned int num_bytes):动态申请size个字节的内存空间。
(2)calloc函数:void *calloc(unsigned n, unsigned size):用于向系统动态申请n个,每个占size个字节的内存空间,并把分配的内存全都初始化为零。
(3)realloc函数:void *realloc(void *p, unsigned size):将指针p所指向的已分配内存区的大小改为size。
(4)free函数:void free(void *p):释放指针p所指向的内存空间。

24.const char * what() const throw()
解析:const throw()是异常规格说明,它表示what()可以抛出异常的类型,类型说明放到()里面,比如throw(int)。如果里面没有类型,那么表示这个函数不抛出任何异常。通常函数后面不写throw()表示该函数可以抛出任何类型的异常。

25.C++多线程编程
解析:
(1)Linux下常用#include <pthread.h>,对应的Windows版本为POSIX Threads for Win32。
(2)C++准标准库中的#include <boost/thread.hpp>。
(3)C++11标准库中的#include
(4)Win32多线程中的#include <windows.h>和#include <process.h>。

26.函数模板
解析:首先,我们定义一个函数模板,如下所示:

// returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller
template <typename T>
int compare(const T &v1, const T &v2) {
    if(v1 < v2) return -1;
    if(v1 > v2) return 1;
    return 0;
}

(1)模板形参表
解析:模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参。
(2)实例化模板函数
解析:编译器能够确定用什么类型代替每个类型形参,以及用什么值代替每个非类型形参。推导出实际模板实参后,编译器使用实参代替相应的模板形参产生并编译该版本的函数。
(3)inline函数模板
template <typename T> inline T min(const T&, const T&) 解析:需要说明的是inline放在模板形参后,返回类型前。在类内定义的函数默认为inline成员函数,而在类外定义的函数前面需加inline才是内联函数。

27.类模板
解析:首先,我们定义一个类模板,如下所示:

template <class Type> class Queue {
public:
    Queue(); // 默认构造函数
    Type& front(); // 返回队头元素的引用
    const Type& front() const;
    void push(const Type&); // 在队尾增加一项
    void pop(); // 从队头删除一项
    bool empty() const; // 指出队列中是否有元素

private:
    // ...
}

当我们使用类模板时,必须显示指定实参,比如Queue< vector > qc; 那么Queue中Type的实际类型为vector
说明:像通常的函数或类一样,我们可以仅对函数模板或类模板进行声明操作而不进行定义操作。

28.模板特殊化
解析:模板特殊化定义:template <> class class_name
(1)在类名称后面必须将使用的具体数据类型写在尖括号<>中,比如template <> class pair {}。
(2)重新定义类的所有成员(成员变量和成员函数)的特殊化实现。

29.模板定义常用方式
解析:
(1)template // 一个class参数
(2)template <class T, class U> // 两个class参数
(3)template <class T, int N> // 一个class和一个整数
(4)template // 有一个默认值
(5)template <int Tfunc (int)> // 参数为一个函数
说明:一般情况,C++模板的声明和定义要放在同一个文件中。

30.指针函数与函数指针
解析:
(1)指针函数本质是函数,该函数返回某一类型指针。函数原型:类型标识符* 函数名(参数表)。比如:int *f(x,y);
(2)函数指针本质是指针,即指向函数的指针变量。函数原型:类型标识符 (*函数名)(参数表)。比如:int (*f)(int x);

31.volatile
解析:volatile关键字确保本条指令不会因编译器的优化而省略,且要求优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

32.条件编译
解析:当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。常用的条件编译指令包括#if,#ifdef,#ifndef,#else,#elif,#endif等。

33.int sprintf( char *buffer, const char *format [, argument] ... );
解析:sprintf打印到字符串中,而printf打印到命令行中。比如sprintf(s, "%d", 123); // 产生字符串"123"。sprintf_s()是sprintf()的安全版本,通过指定缓冲区长度来避免sprintf()存在的溢出风险。

34.int fprintf( FILE *stream, const char *format, [ argument ]...)
解析:fprintf位于头文件<stdio.h>中,其作用是格式化输出到一个流/文件中;函数原型为int fprintf( FILE *stream, const char *format, [ argument ]...),fprintf()函数根据指定的格式(format)向输出流(stream)写入数据(argument)。比如printf(stream, "%d\n", i);

35.C++中的RTTI机制
解析:RTTI(Runtime Type Information)即运行时类型信息,头文件是#include 。如下所示:
(1)typeid(datatype)的返回值类型是type_info类。
(2)typeid(datatype).name()返回当前变量的数据类型(一般数据类型,结构体或类等)。比如,int s; typeid(s).name()。
(3)可以使用type_info类中重载的==和!=运算符比较两个对象的类型是否相等。比如,typeid(*a) == typeid(A)。

36.C++标准库异常类
解析:exception类定义在头文件#include 中,它的两个主要派生类为logic_error和runtime_error,这两个类定义在头文件#include 中(这个头文件包含在#include 中)。logic_error类用于描述程序中出现的逻辑错误,比如传递无效参数等。runtime_error指那些无法预料的事件所造成的错误,比如硬件故障或内存耗尽等。
(1)从logic_error派生的异常类

domain_error:报告违反了前置条件。
invalid_argument:表明抛出这个异常的函数接收到了一个无效的参数。
length_error:表明程序试图产生一个长度大于等于npos的对象(npos是环境尺寸大小的最大可能值,通常为std::size_t)。
out_of_range:报告一个参数越界错误。
bad_cast:抛出这个异常的原因是在运行时类型识别中发现程序执行了一个无效的动态类型转换(dynamic_cast)表达式。
bad_typeid:当表达式typeid(*p)中的参数p是一个空指针时抛出这个异常。

(2)从runtime_error派生的异常类

range_error:报告违反了后置条件。
overflow_error:报告了一个算术溢出错误。
bad_alloc:报告一个失败的存储分配。

说明:size_t(#include )是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。

37.auto_ptr
解析:std::auto_ptr类定义在头文件#include 中,用来实现动态分配对象以及当对象不再需要时自动执行清理。如下所示:

#include <iostream>
#include <memory>
#include <cstddef>
using namespace std;
 
class TraceHeap {
 int i; // private
public:
 static void* operator new (size_t siz){
  void* p = ::operator new(siz);
  cout << "allocating traceheap object on the heap at address " << p << endl;
  return p;
 }
 static void operator delete (void* p) {
  cout << "deleting traceheap object at address " << p << endl;
  ::operator delete(p);
 }
 TraceHeap(int i) : i(i) {}
 int getVal() const { return i; }
};
 
int main() {
 auto_ptr<TraceHeap> pMyObject(new TraceHeap(5));
 cout << pMyObject->getVal() << endl;
 return 0;
} ///:~

说明:尽管程序没有显式删除原始指针,但是在栈反解的时候,pMyObject对象的析构函数会删除该原始指针。

38.static成员函数
解析:
(1)static成员函数是类的组成部分,而不是任何对象的组成部分。
(2)static成员函数没有this指针。
(3)static成员函数不能声明为const。
说明:C++没有原始基类的概念。

39.预定义的宏名称
解析:
(1)__LINE__:整数值,表示当前正在编译的行在源文件中的行数。
(2)__FILE__:字符串,表示被编译的源文件的文件名。
(3)__DATE__:一个格式为"Mmm dd yyyy"的字符串,存储编译开始的日期。
(4)__TIME__:一个格式为"hh:mm:ss"的字符串,存储编译开始的时间。
(5)__cplusplus:整数值,所有C++编译器都定义了这个常量为某个值。如果这个编译器是完全遵守C++标准的,它的值应该等于或大于199711L,具体值取决于它遵守的是哪个版本的标准。
说明:C++中常用的预处理指令有#define,#undef,#ifdef,#ifndef,#if,#endif,#else,#elif,#line,#error,#include,#pragma等。

40.高级类型转换
解析:ANSI-C++标准定义了4种类型转换操作符reinterpret_cast <new_type> (expression);dynamic_cast <new_type> (expression);static_cast <new_type> (expression);const_cast <new_type> (expression)。其中,new_type是要转换成的目标类型,expression是要被转换的内容。如下所示:
(1)reinterpret_cast:可以将一个指针转换为任意其它类型的指针。它也可以用来将一个指针转换为一个整型,或反之亦然。
(2)static_cast:执行所有能够隐含执行的类型转换,以及它们的反向操作(即使这种方向操作是不允许隐含执行的)。
(3)dynamic_cast:用来进行任何可以隐含进行的转换操作以及它们被用于多态类情况下的方向操作。
(4)const_cast:这种类型转换对常量const进行设置或取消操作。

41.文件的输入输出
解析:C++中支持文件的输入输出类:ofstream写操作(输出)的文件类(继承ostream类);ifstream读操作(输入)的文件类(继承istream类);fstream可同时读写操作的文件类(继承iostream派)。
(1)打开文件模式

ios::in:为输入(读)而打开文件。
ios::out:为输出(写)而打开文件。
ios::ate:初始位置为文件尾。
ios::app:所有输出附加在文件末尾。
ios::trunc:如果文件已存在则先删除该文件。
ios::binary:二进制方式。

说明:ofstream,ifstream和fstream类的成员函数open包含默认打开文件的方式,分别为ios::out | ios::trunc,ios::in,os::in | ios::out。
(2)eof和getline函数

eof是ifstream从类ios中继承过来的,当到达文件末尾时返回true
getline函数的作用是从输入流中读取一行字符,语法istream& getline (istream& is, string& str, char delim)。

(3)状态标志符

bad():如果在读写过程中出错,那么返回true
fail():如果在读写过程中出错,或格式错误,那么返回true
eof():如果读文件到达文件末尾,那么返回true
good():如果没有以上错误,那么返回true
clear():重置以上成员函数所检查的状态标志。

(4)获得和设置流指针

ifstream:有一个被称为get pointer的指针,指向下一个将被读取的元素。
ofstream:有一个被称为put pointer的指针,指向写入下一个元素的位置。
fstream:同时继承了get和put属性。

说明:ofstream类,ifstream类和fstream类均在头文件#include 中。

42.struct与class
解析:struct继承class是public继承,而class继承struct是private继承。

43.SLAM
解析:SLAM(simultaneous localization and mapping)即时定位与地图构建。

44.动态绑定和静态绑定
解析:
(1)对象的静态类型:对象在声明时采用的类型,是在编译期确定的。
(2)对象的动态类型:目前所指对象的类型,是在运行期决定的。
(3)静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
(4)动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。
说明:对象的动态类型可以改变,但是静态类型不能改变。只有虚函数使用的是动态绑定,其他的全部使用的是静态绑定(包括缺省参数)。

45.文件位置指针
解析:istream提供了用于重新定位文件位置指针的成员函数seekg,ostream提供了用于重新定位文件位置指针的成员函数seekp。如下所示:
(1)fileObject.seekg( n );
(2)fileObject.seekg( n, ios::cur );
(3)fileObject.seekg( n, ios::end );
(4)fileObject.seekg( 0, ios::end );
说明:seekg和seekp的第一个参数通常是一个长整型,第二个参数用于指定查找方向,其中ios::beg表示从流的开头开始定位(默认),ios::cur表示从流的当前位置开始定位,ios::end表示从流的末尾开始定位。

46.C++标准异常
解析:C++标准异常定义在头文件#include 中,如下所示:
(1)std::exception:该异常是所有标准C++异常的父类。
(2)std::bad_alloc:该异常可以通过new抛出。
(3)std::bad_cast:该异常可以通过dynamic_cast抛出。
(4)std::bad_exception:这在处理C++程序中无法预期的异常时非常有用。
(5)std::bad_typeid:该异常可以通过typeid抛出。
(6)std::logic_error:理论上可以通过读取代码来检测到的异常。
(7)std::domain_error:当使用了一个无效的数学域时,会抛出该异常。
(8)std::invalid_argument:当使用了无效的参数时,会抛出该异常。
(9)std::length_error:当创建了太长的std::string时,会抛出该异常。
(10)std::out_of_range:该异常可以通过方法抛出,比如std::vector和std::bitset<>::operator
(11)std::runtime_error:理论上不可以通过读取代码来检测到的异常。
(12)std::overflow_error:当发生数学上溢时,会抛出该异常。
(13)std::range_error:当尝试存储超出范围的值时,会抛出该异常。
(14)std::underflow_error:当发生数学下溢时,会抛出该异常。

47.C++标准库
解析:
(1)标准函数库:这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自C语言。

输入/输出 I/O
字符串和字符处理
数学
时间、日期和本地化
动态分配
宽字符函数
其它

(2)面向对象类库:这个库是类及其相关函数的集合。

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

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

48.C/C++常用头文件
解析:
(1)#include :STL双端队列容器。
(2)#include :异常处理类。
(3)#include :文件输入/输出。
(4)#include :STL定义运算函数(代替运算符)。
(5)#include :定义各种数据类型最值常量。
(6)#include :STL线性列表容器。
(7)#include :STL映射容器。
(8)#include :参数化输入/输出。
(9)#include :基本输入/输出支持。
(10)#include :基于字符串的流。
(11)#include :STL堆栈容器。
(12)#include :STL通用算法。
(13)#include :STL位集容器。
(14)#include :字符处理。
(15)#include :标准异常类。
(16)#include :底层输入/输出支持。
(17)#include :字符串类。
(18)#include :STL通用模板类。
(19)#include :STL动态数组容器。
(20)#include :输入/输出系统使用的前置声明。
(21)#include :定义错误码。
(22)#include :定义本地化函数。
(23)#include :定义数学函数。
(24)#include :复数类。
(25)#include :定义输入/输出函数。
(26)#include :定义杂项函数及内存分配函数。
(27)#include :字符串处理。
(28)#include :定义关于时间的函数。
(29)#include :数据流输入/输出。
(30)#include :基本输入流。
(31)#include :基本输出流。
(32)#include :STL队列容器。
(33)#include :STL集合容器。
(34)#include :宽字符处理及输入/输出。
(35)#include :宽字符分类。
(36)#include <complex.h>:复数处理。
(37)#include <fenv.h>:浮点环境。
(38)#include <inttypes.h>:整数格式转换。
(39)#include <stdbool.h>:布尔环境。
(40)#include <stdint.h>:整型环境。
(41)#include <tgmath.h>:通用类型数学宏。

49.完全安装Boost
解析:Boost库是为C++语言标准库提供扩展的一些C++程序库的总称。安装实现的功能,Boost大致可分为20类:
(1)字符串和文本处理。
(2)容器。
(3)迭代器。
(4)算法。
(5)函数对象和高阶编程。
(6)泛型编程。
(7)模板元编程。
(8)预处理元编程。
(9)并发编程。
(10)数学和数字。
(11)排错和测试。
(12)数据结构。
(13)图像处理。
(14)输入输出。
(15)跨语言混合编程。
(16)内存管理。
(17)解析。
(18)编程接口。
(19)杂项。
(20)编译器问题的变通方案。

参考文献:
[1]cplusplus:http://www.cplusplus.com/
[2]C++的const类成员函数:http://blog.csdn.net/lihao21/article/details/8634876
[3]C++拷贝构造函数详解:http://blog.csdn.net/lwbeyond/article/details/6202256
[4]C++ Primer(第4版)
[5]volatile:http://baike.baidu.com/link?url=VEBsQt5II-QxbLx-CrpazjHbyWt5tVMflp_EaCSK_n50c5KABprxEgfnq1mdn_Krjzeq_cpybReD4H2epmPDya
[6]条件编译:http://baike.baidu.com/link?url=x92_9-h5i4tA01RIUg-0aqO6M1n77uv2u7zpA1Mcp9TTVlTYMm6lQGq4EE3Mvyf25fapXG00KJQysT1mAADqxq
[7]类型转换高级:http://www.prglab.com/cms/pages/c-tutorial/advanced-concepts/class-type-casting.php
[8]深入理解 C++ 的动态绑定和静态绑定:http://blog.csdn.net/chgaowei/article/details/6427731
[9]C++标准库:http://www.runoob.com/cplusplus/cpp-standard-library.html
[10] Boost C++ Libraries:http://www.boost.org/