[toc]
组织
文件
包
文件
文件名后缀
说明
.c
c 源文件
.h
c 同文件
.cpp
c++ 源文件
.hpp
c++ 头文件
.hh
c++ 头文件
.hxx
c++ 头文件
.h++
c++ 头文件
原则
通常的,.h
和 .c
对应 c 代码,.hpp
和 .cpp
对应 c++ 代码
保持 .h
文件是 c 兼容的代码(不包含 c++ 代码)
如果想编写 c 和 c++ 的混合代码
可以在 .hpp
中使用 extern "C"
来实现
不要使用 .H
和 .C
后缀,因为部分文件系统不区分大小写,比如 windows,macos 在格式化分区时也有不区分大小写的选项
输入输出
标准输入输出包含:
1 2 3 4 5 6 while (cin >> num) sum += num; cin >> Item;
基础
变量
初始化
C++ 支持两种初始化方式,复制初始化和直接初始化。
1 2 int val (1024 ) ; int val = 1024 ;
对于内置类型来说,复制初始化和直接初始化几乎没有差别。函数体外定义的内置变量都初始化成0,函数体内定义的内置变量不进行自动初始化。变量在使用前必须被定义,且只允许被定义一次。
声明
为了让多个文件可以访问相同的变量,C++ 区分了声明和定义。声明用于向程序表明变量存在,及其类型和名字;定义用于为变量分配空间,还可对变量进行初始化。
1 2 3 4 extern int i; int i; extern int i = 1 ;
数据类型
类型
含义
最小存储空间
bool
布尔型
—
char
字符
8位
wchar_t
宽字符型
16位
short
短整型
16位
int
整型
16位
long
长整型
32位
float
单精度浮点数
6位有效数字
double
双精度浮点型
10位有效数字
long double
扩展精度浮点型
10位有效数字
类型
数字
字符串
初始化
子串
1 2 str.substr (3 , 5 ); str.substr (5 );
布尔
限定
static
1 2 3 4 5 6 7 class A {public : static A Instance () { static A _a; return _a; } };
常量
定义
数据结构
数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int i[5 ];int j[2 ][2 ];int i[] = {1 , 2 , 3 };int j[][1 ] = {{1 }, {2 }, {3 }};int k[2 ][2 ] = {{1 , 2 }, {3 }};1 2 3 0 int i[5 ] = {0 }; std::cout << sizeof (i) << std::endl; int b[3 ][3 ] = {0 }; int size = 3 ;int *c = new int [size]; std::cout << sizeof (c) << " - " << sizeof (*c) << std::endl; memset (c, 0 , size * sizeof (*c)); delete [] c;
列表
1 2 3 vector<int > iv{1 , 2 , 3 } vector<int > iv (3 , 1 ) ;
集合
映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 std::map<int , int > m = { {1 , 2 }, {2 , 3 } }; std::map<std::string, std::vector<int > > mapOfOccur = { { "Riti" , { 3 , 4 , 5 , 6 } }, { "Jack" , { 1 , 2 , 3 , 5 } } }; std::map<int , int > m = ...; for (auto &entry : m) { std::cout << entry.first << " -> " << entry.second << std::endl; } map<int , string> mp; mp.insert (pair <int ,string>(1 ,"aaaaa" )); mp.insert (make_pair <int ,string>(2 ,"bbbbb" )); mp.insert (map<int , string>::value_type (3 ,"ccccc" )); mp[4 ] = "ddddd" ; std::map<char ,int > mp; mp.emplace ('x' ,100 ); std::map<char ,int >::iterator it = mp.find ('x' ); if (it != mp.end ()) else std::map<char ,int >::iterator it = mp.find ('x' ); if (it != mp.end ()) mp.erase (it);
语法
程序结构
注释
运算符
条件控制
循环
判断
函数
类
特殊成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 classname ()explicit classname (type param) classname (const classname &other) classname& operator =(const classname &other)classname (classname &&other)classname& operator =(classname &&other) ~classname ()
Function
syntax for class MyClass
Default constructor
MyClass();
Copy constructor
MyClass(const MyClass& other);
Move constructor
MyClass(MyClass&& other) noexcept;
Copy assignment operator
MyClass& operator=(const MyClass& other);
Move assignment operator
MyClass& operator=(MyClass&& other) noexcept;
Destructor
~MyClass();
特性
语法糖
default
default
关键词为类的特殊默认无参 函数(构造、析构、拷贝构造、拷贝赋值)提供默认行为。
1 2 3 4 5 6 7 8 9 10 11 class A { public : A () = default ; A (const A&); A& operator = (const A&); ~A () = default ; }; A::A (const X&) = default ; A& A::operator = (const A&) = default ;
delete
和 default
,屏蔽默认行为。
1 2 3 4 5 6 7 class A { A& operator =(const A&) = delete ; }; A a, b; a = b;
thread_local
lambda
lambda 表达式格式如下。
1 [函数对象参数] (操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}
函数对象参数
值
参数范围
参数传递方式
备注
空
没有函数对象参数
-
-
=
表达式所有可访问局部变量(包括所在类的 this 对象)
值传递
-
&
表达式所有可访问局部变量(包括所在类的 this 对象)
引用传递
-
this
函数体内可以使用 Lambda 所在类中的成员变量
TBD
-
a
a
值传递
变量默认为 const,如果需要修改需为函数体添加 mutable 修饰符
&a
a
引用传递
a,&b
a,b
a 为值传递,b 为引用传递
-
=,&a,&b
表达式所有可访问局部变量(包括所在类的 this 对象)
a、b 引用传递,其他参数是值传递
-
&,a,b
表达式所有可访问局部变量(包括所在类的 this 对象)
a、b 值传递,其他参数是引用传递
-
空指针处理
函数式编程
泛型编程
1 2 3 4 5 6 7 8 9 10 template <typename T>T r () { T t; cin >> t; return t; } int x = r <int >();
1 2 3 4 5 6 7 8 9 10 11 12 template <typename T>void swapT (T& a, T& b) { a ^= b; b ^= a; a ^= b; } vector<int > iv{1 , 2 , 3 }; swapT (iv[0 ], iv[2 ]);
不限于类型。
1 2 3 4 5 6 7 8 9 template <unsigned N>void f () { std::cout << N << std::endl; } int main () { f <10 >(); return 0 ; }
类型推演
重用方法
1 2 3 std::is_same<TA, TB> typeid() std::is_same_v<TA, TB> #include <variant>
类型读取及定义
1 2 template <auto object, class T =std::decay_t <decltype (*object)>>int Function ();
类型判断
1 2 3 4 5 6 7 8 9 #include <concepts> template <typename Type> concept CharTypes = std::is_same<Type, char >::value || std::is_same<Type, wchar_t >::value || std::is_same<Type, char8_t >::value || std::is_same<Type, char16_t >::value || std::is_same<Type, char32_t >::value; template <CharTypes T> class Some {};
1 2 3 4 5 6 7 8 #include <variant> template <class T>void f (T t) { if (std::is_same_v<T, std::string>) { } }
宏定义 define
##
连接形参,忽略前后空白符。
1 2 3 4 5 6 #define Concat(a, b) a##b int ab = 1 , ax = 2 , xa = 3 ;std::cout << Concat (a, b) << std::endl; std::cout << AppendX (a) << std::endl; std::cout << XAppend (a) << std::endl;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #define select(m, key) m##[#key] #define select(m, key) (m)[#key] #define select(m, key) m##.##key #define select(m, key) m.##key #define select(m, key) m.key std::map<std::string, std::string> m; m["a" ] = "0" ; auto v = select (m, a);
#@
字符化形参。
#
字符串化形参。
1 2 3 4 5 6 #define ToString(a) #a std::cout << ToString (abc) << std::endl; #define ToSV(member) #member##sv ToSV (time)
Parameter pack
Parameter pack 。
A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments.
A template with at least one parameter pack is called a variadic template .
包含至少一个参数包的模板称为可变模板。
右值引用&&
C++ 11 引入右值引用主要是为了解决以下几个问题:
优化复制大对象的性能问题。
在传递一个对象时,如果使用常规的左值引用,就需要进行拷贝构造函数的调用,这会导致复制大对象的时候开销很大。而右值引用可以避免这种情况的发生。因为右值引用本身不会进行对象的拷贝操作,只是将对象所在的内存地址绑定到右值引用上,从而提高代码执行效率。
实现移动语义,支持转移资源所有权。
在C++11中,新增了std::move函数,可以将一个对象的资源所有权转移到另一个对象中,这就是移动语义。通过将对象的内部数据指针从源对象转移到目标对象,可以避免创建和销毁临时对象,从而提高代码执行效率。而实现移动语义,需要使用右值引用的特性。
总之,右值引用的引入,旨在提高C++代码的性能和效率,支持更加高效的对象传递和资源管理方式,并且为C++编程带来更多的灵活性和扩展性。
其他优化场景。
函数中返回一个临时变量时,编译器会自动调用移动构造函数,并将临时变量的资源所有权移动到函数的返回值中,从而避免进行数据拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 std::string GetString () { std::string t = "abc" ; std::string res = t + "def" ; std::cout << "A " << static_cast <void *>(res.data ()) << std::endl; return res; } int main () { auto r = GetString (); std::cout << "B " << static_cast <void *>(r.data ()) << std::endl; std::cout << "---" << std::endl; auto r2 = std::move (GetString ()); std::cout << "B " << static_cast <void *>(r2. data ()) << std::endl; return 0 ; }
注意
其他
常量
进阶
C++ 程序质量保障
代码覆盖率(code coverage)
内存检查
CPU Profiler
malloc
常用的 malloc 库,及实践。
jemalloc
tcmalloc
mimalloc
RAII
RAII(Resource Acquisition Is Initialization,资源获取即初始化)使用局部变量来管理资源,是 C++ 中常用的资源管理方式。
时间
time unit
std::chrono::microseconds
std::chrono::milliseconds
std::chrono::second
std::chrono::minutes
std::chrono::hours
std::chrono::days
std::chrono::months
std::chrono::years
clock
steady_clock 单调递增时钟
system_clock 系统时间时钟
high_resolution_clock 高精度时钟
time_point
duration
duration_cast
1 std::chrono::time_point<Clock,Duration>::time_point
sample
1 2 3 4 5 using namespace std::chrono_literals; std::chrono::system_clock::now (); std::chrono::duration (10 s);