主要整理了N多年前(2010年)学习C++的时候开始总结的知识点,好长时间不写C++代码了,现在LLM量化和推理需要重新学习C++编程,看来出来混迟早要还的。
1.const_cast <new_type> (expression)[1]
解析:const_cast转换符用来移除变量的const或volatile限定符。如下所示:
(1)常量指针被转化成非常量指针,并且仍然指向原来的对象。比如,const A *pca1 = new A; A *pa2 = const_cast<A*>(pca1);
(2)常量引用被转换成非常量引用,并且仍然指向原来的对象。比如,const A &a1 = a0; A a2 = const_cast<A&>(a1);
(3)常量对象被转换成非常量对象(错误)。 比如,const A ca; A a = const_cast<A>(ca);
(错误)
(4)添加const属性。比如,const int *k = const_cast<const int*>(j);和const int *m = j;
说明:使用const_cast去掉const属性,其实并不是真的改变原类类型(或基本类型)的const属性,它只是又提供了一个接口(指针或引用),可以通过这个接口来改变类型的值。使用const_case添加const属性,也是提供了一个接口,来不让修改其值。
2.VS 2013和Boost 1.6.2[2]
解析:
(1)附加包含目录:D:\boost_1_62_0
(2)附加库目录:D:\boost_1_62_0\stage\lib
在VS 2013工程中,添加C/C++工程中外部头文件及库的基本步骤,如下所示:[4]
(1)添加工程的头文件目录:工程 --> 属性 --> 配置属性 --> C/C++ --> 常规 --> 附加包含目录:加上头文件存放目录。
(2)添加文件引用的lib静态库路径:工程 --> 属性 --> 配置属性 --> 链接器 --> 常规 --> 附加库目录:加上lib文件存放目录。
(3)添加工程引用的lib文件名:工程 --> 属性 --> 配置属性 --> 链接器 --> 输入 --> 附加依赖项:加上lib文件名。
(4)添加工程引用的dll动态库:把引用的dll放到工程的可执行文件所在的目录下。
说明:b2.exe、bjam.exe这两个exe的作用是一样的,只不过bjam.exe是老版本,b2是bjam的升级版本。
3.VS 2013和Boost.Python [3][5]
解析:Boost::Python库是Python和C++相互交互的框架,它是对Python/C API的包装,可以在Python中调用C++的类和方法,也可以让C++调用Python的类和方法。Python是一个动态类型的语言,C++是一个静态类型的语言,对于Python中的变量类型,Boost.Python都有相应的类对应。
(1)编译Boost.Python
执行命令bjam --with-python link=shared runtime-link=shared address-model=64,在目录D:\boost_1_62_0\stage\lib下面生成boost_python-vc120-mt-1_62.dll,boost_python-vc120-mt-1_62.lib,boost_python-vc120-mt-gd-1_62.dll,boost_python-vc120-mt-gd-1_62.lib四个文件。如果报错fatal error C1001:编译器中发生内部错误,那么将VS 2013升级到VS 2013 Update 5。[7]
(2)使用VS 2013生成dll文件
使用VS 2013新建一个Win32 DLL项目,然后设置项目属性:包含目录D:\boost_1_62_0,D:\boost_1_62_0\libs,D:\Program Files\Anaconda2\include,库目录D:\boost_1_62_0\stage\lib,D:\Program Files\Anaconda2\libs,并且不启用最小重新生成,不使用预编译头。
(3)Python调用C++
将生成的dll文件改为pyd文件,并将boost_python-vc120-mt-gd-1_62.dll和pyd文件复制到Python项目的根目录。[8][9]
说明:通过Boost.Python模块(也是对Python/C API的封装),C++可为Python编写扩展模块。通过Python/C API,Python可为C++提供脚本接口。[10]
4.chrono、ratio和ctime等头文件 [6]
解析:
(1)#include :日期和时间。
(2)#include :日期和时间。
(3)#include :比例关系。
(4)#include :运行时类型信息(RTTI)。
5.两种遍历host_vector方式
解析:
(1)常规方式
for (int i = 0; i < h_vec.size(); i++) {
cout << h_vec[i] << endl;
}
(2)迭代器方式
for (host_vector<int>::iterator i = h_vec.begin(); i != h_vec.end(); i++)
{
cout << *i << endl;
}
6.volatile关键字
解析:volatile关键字确保本条指令不会因编译器的优化而省略,而且要求每次直接读值。
7.extern "C"
解析:extern "C"的主要作用是为了能够正确实现C++代码调用其它C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。
8.C++ 11中auto功能[11]
解析:自动类型推断;返回值占位。
9.assert宏
解析:assert()是宏,而不是函数。在C的#include<assert.h>头文件中,其作用是如果它的条件返回错误,则终止程序执行。如下所示:
#include <stdio.h>
#include <assert.h>
void print_number(int* myInt) {
assert(myInt != NULL);
printf("%d\n", *myInt);
}
int main()
{
int a = 10;
int * b = NULL;
int * c = NULL;
b = &a;
print_number(b);
print_number(c);
return 0;
}
10.inline关键字
解析:关键字inline必须与函数定义体放在一起才能使函数成为内联函数,仅将inline放在函数声明前面不起任何作用。不宜使用内联函数,如下所示:
(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。
11.exit()函数
解析:exit(1)是异常退出,exit(0)是正常退出。
12.C++三法则
解析:如果类定义下列其中一个函数,那么也需要其它两个函数,如下所示:
(1)析构函数(Destructor)
(2)复制构造函数(copy constructor)
(3)复制赋值运算符(copy assignment operator)
13.POD类型
解析:POD是Plain Old Data的缩写,它是一个struct或者类,且不包含构造函数、析构函数以及虚函数。
14.虚函数,纯虚函数,虚基类与虚继承
解析:
(1)虚函数:定义一个函数为虚函数,不代表函数为不被实现的函数。定义它为虚函数是为了允许用基类的指针来调用子类的这个函数。
(2)纯虚函数:定义一个函数为纯虚函数,才代表函数没有被实现。定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
15.std::shared_ptr
解析:std::shared_ptr定义于头文件 中,template< class T > class shared_ptr; std::shared_ptr是通过指针保持某个对象的共享拥有权的智能指针。若干个shared_ptr对象可以拥有同一个对象;最后一个指向该对象的shared_ptr被销毁或重置时,该对象被销毁。销毁该对象时使用的是delete表达式或者是在构造shared_ptr时传入的自定义删除器(deleter)。shared_ptr也可以不拥有对象,称作空(empty)。shared_ptr满足CopyConstructible和CopyAssignable的要求。
16.explicit specifier
解析:在大部分情况中,隐式转换却容易导致错误(不是语法错误,编译器不会报错)。通过将构造函数声明为explicit(显式)的方式可以抑制隐式转换,也就是explicit构造函数必须显式调用。如下所示:
struct A {
A ( int ) {}
operator int() const { return 0; }
};
struct B {
explicit B(int) {}
explicit operator int() const { return 0; }
};
int main() {
// A is has no explicit ctor / conversion, everything is fine
A a1 = 1;
A a2 ( 2 );
A a3 { 3 };
int na1 = a1;
int na2 = static_cast<int>( a1 );
B b1 = 1; // Error: implicit conversion from int to B
B b2 ( 2 ); // OK: explicit constructor call
B b3 { 3 }; // OK: explicit constructor call
int nb1 = b2; // Error: implicit conversion from B to int
int nb2 = static_cast<int>( b2 ); // OK: explicit cast
}
说明:explicit class_name ( params );explicit operator type () (C++11起)。
17.boost::mutex
解析:Boost线程库提供了6种互斥体类型:boost::mutex;boost::try_mutex;boost::timed_mutex;boost::recursive_mutex;boost::recursive_try_mutex;boost::recursive_timed_mutex。boost库中提供了mutex类与lock类,通过组合可以轻易的构建读写锁与互斥锁。如下所示:
(1)mutex对象类:mutex类主要有两种:boost::mutex,boost::shared_mutex,其中mutex有lock和unlock方法,shared_mutex除了提供lock和unlock方法外,还有shared_lock和shared_unlock方法。因此,boost::mutex为独占互斥类,boost::shared_mutex为共享互斥类。
(2)lock模板类:boost::unique_lock,boost::shared_lock,其中unique_lock为独占锁,shared_lock为共享锁。unique_lock中的T可为mutex类中的任意一种,如果为shared_mutex,那么boost::unique_lock类的对象构造函数构造时,会自动调用shared_mutex的shared_lock方法,析构函数里会自动调用shared_mutex的shared_unlock方法。如果boost:: unique_lock,则分别自动调用lock和unlock方法。boost::shared_lock中的T只能是shared_mutex类。
18.NMake Makefiles与MinGW Makefiles区别
解析:-G "MinGW Makefiles"这个参数的意思是生成MinGW的Makefile,最终生成的编译目标(Makefile)是针对MinGW编译器的。如果编译器是VS,那么使用"NMake Makefiles"。
19.Boost并发编程[12]
解析:
(1)Interprocess (IPC)库:用于实现共享内存、内存映射的 I/O 和消息队列;
(2)Thread库:用于实现可移植的多线程;
(3)Message Passing Interface (MPI):库用于分布式计算中的消息传递;
(4)Asio库:用于使用套接字和其它低层功能实现可移植的连网功能。
20.CMake常用命令
解析:
(1)set(Foo a b c):设置变量Foo。
(2)add_exectuable:告诉工程生成一个可执行文件。
(3)add_library:告诉工程生成一个库文件。
(4)include_directories:头文件路径。
(5)link_directories:库文件路径。
(6)find_package(XXX):调用FindXXX.cmake模块。
(7)add_definitions:添加编译参数。
(8)target_link_libraries:添加链接库。
(9)CMAKE_BUILD_TYPE:SET(CMAKE_BUILD_TYPE Debug|Release)。
(10)编译器参数:CMAKE_C_FLAGS;CMAKE_CXX_FLAGS。
(11)_FOUND:如果找到了name,被设置为1,否则不设置。
(12)_INCLUDE_DIRS:被设置成name安装头文件和依赖头文件的目录。
(13)_LIBRARIES:被设置成所建立和安装的name库的文件名。
(14)_LIBRARY_DIRS:被设置成name库的第三方依赖文件所在的目录。
(15)_VERSION:所找到的name的版本。
(16)_COMPONENTS:列出所有可用组件。
(17)_DEFINITIONS:列出所需要的预处理器定义和编译器标志。
(18)获得一个目录下所有源文件(不包含头文件):aux_source_directory(<dir> <variable>)。
(19)设定依赖的cmake版本:cmake_minimum_required(VERSION 2.6)。
(20)${projectname_SOURCE_DIR}
:表示根源文件目录。
(21)${projectname _BINARY_DIR}
:表示根二进制文件目录。
(22)打印make输出:make VERBOSE=1。
(23)add_compile_options:添加的编译选项是针对所有编译器的。
(24)executable_output_path:指定可执行文件存放的路径。
(25)library_output_path:指定库文件存放的路径。
(26)cmake_current_source_dir:指的是当前处理的CMakeLists.txt所在的路径。
(27)cmake_current_binary_dir:如果是out-of-source编译,指的是target编译目录。
(28)cmake_current_list_file:输出调用这个变量的CMakeLists.txt完整路径。
(29)cmake_current_list_line:输出这个变量所在的行。
(30)cmake_module_path:定义cmake模块所在的路径。
(31)cmake调用环境变量:使用$ENV{NAME}指令调用系统环境变量。
(32)UNIX:在所有的类UNIX平台为TRUE,包括OS X和cygwin。
(33)WIN32:在所有的win32平台为TRUE,包括cygwin。
(34)build_shared_libs:控制默认的库编译方式。
21.#include
解析:io代表输入输出,manip是manipulator[操纵器]的缩写。它是I/O流控制头文件,就像C里面的格式化输出一样。
22.#define WIN32_LEAN_AND_MEAN
解析:包含<windows.h>时去除一些头文件的包含,加快编译速度。
23.#define NOMINMAX
解析:为了禁用Visual C++中的min/max宏定义,可以在包含<windows.h>头文件之前加上#define NOMINMAX。
24.标准库bitset对象上的操作
解析:
1\]b.any():b中是否存在置为1的二进制位。
\[2\]b.none():b中不存在置为1的二进制位。
\[3\]b.count():b中置为1的二进制位的个数。
\[4\]b.size():b中二进制位的个数。
\[5\]b\[pos\]:访问b中在pos处的二进制位。
\[6\]b.test(pos):b中在pos处的二进制位是否为1。
\[7\]b.set():把b中所有二进制位都置为1。
\[8\]b.set(pos):把b中在pos处的二进制位置为1。
\[9\]b.reset():把b中所有二进制位都置为0。
\[10\]b.reset(pos):把b中在pos处的二进制位置为0。
\[11\]b.flip():把b中所有二进制位逐位取反。
\[12\]b.flip(pos):把b中在pos处的二进制位取反。
\[13\]b.to_ulong:把b中同样的二进制位返回一个unsigned long值。
\[14\]os \<\< b:把b中的位集输出到os流。
**25.GCC参数**
解析:
[1]static:编译静态库。
[2]shared:编译动态库。
[3]w:不生成任何警告信息。
[4]Wall:生成所有警告信息。
[5]-l [小写l]指定要链接的库。
[6]-I [大写i]指定头文件目录。
[7]-L [大写l]指定库目录。
**26.Binutils**
解析:GNU Binutils \[Binary Utilities\],即GNU二进制工具集。
**27.itoa函数\[#include \
9\]其它运算符:()(函数调用),-\>(成员访问),,(逗号),[](%E4%B8%8B%E6%A0%87)
**35.不可重载运算符**
解析:
\[1\].:成员访问运算符
\[2\].*和-\>* :成员指针访问运算符
\[3\]:::域运算符
\[4\]sizeof:长度运算符
\[5\]?::条件运算符
\[6\]#:预处理符号
说明:运算重载符不可以改变语法结构,不可以改变操作数的个数,不可以改变优先级,不可以改变结合性。
**36.虚函数**
解析:虚函数是在基类中使用关键字virtual声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
**37.纯虚函数**
解析:virtual int area() = 0;其中,=0告诉编译器,函数没有主体,上面的虚函数是纯虚函数。
**38.使用CLion进行Boost编程**
解析:
\[1\]./booststrap.sh
\[2\]sudo ./b2 install
说明:编译好的头文件位于/usr/local/include/boost,库路径位于/usr/local/lib。
**39.ADD_EXECUTABLE(CRNode ${SRC_LIST})**
解析:定义了这个工程会生成一个文件名为CRNode的可执行文件,相关的源文件是SRC_LIST中定义的源文件列表。需要注意的是,这里的CRNode和之前的项目名称没有任何关系,可以任意定义。
**40.TARGET_LINK_LIBRARIES(CRNode log4cpp thrift)**
解析:在指定链接目标文件的时候需要链接的外部库,其效果类似gcc的编译参数-l,可以解决外部库的依赖问题。
**41.C类库**
解析:
[1]:List header (header)
[6]