时隔多年又开始拾起CPP 开始使用,以前一直用的C++98,而今 C++20都已经出来了。为了方便自己查阅新语法规则,所以将自己遇到的CPP语法规则归纳总结方便查阅。
一、数据类型
1.1 std::option<type> 代表type类型的值可能存在也可能由于失败是不存在值的类型
std::optional<string> testfunc()
{
if( success)
{
return "result data";
}
return {}; //失败了返回空
}
auto ret = testfunc();
if(ret)
{
//ret 有值
}
else
{
//ret 无值
}
string res = ret.value_or("如果 ret 没值,则返回这个字符串");
1.2 std::variant<type1, type2> 类似c 中的 union 可以定义个支持多种类型的类型,并且内部维护了自己是什么类型的逻辑,相比 union std::varaint 占的内存是他所有类型元素的总和。
std::variant<string, int> data;
data = "hello";
cout << std::get<string>(data) <<endl;//print hello
data = 4;
cout << std::get<int>(data) <<endl;//print 4
cout << std::get<string>(data) <<endl;//编译通过,但是runtime会报错,显示std::bad_variant_access
data = false;//能编译通过
cout << std::get<bool>(data) <<endl;//这句编译失败
// 如果data存的数据是string类型的数据
if(auto p = std::get_if<string>(&data)){
string& s = *p;
}
variant<int, double>s;
cout << sizeof(int) <<endl;//4
cout << sizeof(double) <<endl;//8
cout << sizeof(s) <<endl;//16,这里应该都会有字节对齐
//sizeof(s) = sizeof(int) + sizeof(double);
1.3 std::any
自由类型,能保存任何类型的数据,虽然更加自由,但是他比 std::variant类型性能要低些,而且类型安全性没有variant强
// 方法一,创建一个std::any对象
std::any data = std::make_any<int>(4);
// 方法二,创建一个std::any对象
std::any data;
data = 4;
// 可以对data进行任意类型的赋值
data = "hello world";
data = false;
二、类
2.1 类成员属性,可以再申明时指定默认值
class Test { private: int m_a = 0; };
三、模板
3.1 尾置返回类型
用于在模板函数中由于模板参数不定我们没办法推断函数返回类型时使用,由于尾置返回的类型由 decltype() 得到,有时候我们需要这这些类型做些处理才是我们想要的,那么可以配合内置函数 5.1 使用
//返回迭代器引用 template<typename It> auto func(It beg) -> decltype(*beg) { return *beg; } /* 通过尾置返回类型的定义,我们可以通过 decltype 分析得到*beg 类型 为了丰富尾置返回,还内置了一系列的标准款函数 */
3.2 不定模板参数
用于定义参数不定的模板
template<typename ...ARGS> void foo(const ARGS& ... args){} //实例调用如下 foo(1, true, std::string("test")) ///会自动推导出 foo(int, bool, std::string)的函数
3.3 sizeof...(args)
用于获得不定参数模板类获得参数数量
template<typename ...Args> void func(const Args&... args) { cout << sizeof...(Args) << endl; // 类型参数得的数量 count << sizeof...(args) << endl; //函数参数的数量 }
3.4 定义模板别名
template<typename T>
class Test{}
template<T>
using TestOtherName = Test<T>
TestOtherName<int> a; //等价于 Test<int>
四、语法规则
4.1 auto 类型
用于编译阶段能自动推导出类型的 动态类型申明。有时候我们赋值操作时申明类型需要去看我们赋值对象的类型然后写对应类型。auto 申明的变量必须赋值,否则无法编译时就推导出类型了。
int a = 1, b = 2; auto c = a + b; // c 将推导为 int
4.2 decltype 函数
在运行阶段动态推导类型。
double a = 10.123; int b = 20; decltype(a+b) c; //这里和auto不一样,不需要立即赋值,但 c = a + b;
4.3 final 修饰 class 不允许被继承,虚函数不允许再被重写
class Test final {}; // 类 Test 将不能被继承 class Test1 { virtual void func() final; // 函数 func 将不能再被子类重写了。 }
五、新库
5.1 模板类型处理
remove_reference<T> 返回去掉T 的引用属性的普通类型 X&/X&& -> X
add_const<T> 返回T 类型增加 const 修饰变成常量类型 X ->> const X
add_lvalue_reference<T> 返回T 对应的 左值引用类型 X -> X&
add_rvalue_reference<T> 返回T 对应的右值引用类型 X -> X&&
remove_pointer<T> 去掉T的指针修饰,变成对应的值类型 X* -> X
add_pointer<T> 给T增加指针修饰,变成T类型的指针类型 X -> X*
make_signed<T> 将无符号类型,变成有符号类型 unsigned X -> X
make_unsigned<T> 将有符号类型变成无符号类型 signed X -> unsigned X
remove_extent<T> 去掉一维数组修饰 X[n] -> X
remove_all_extentx 去掉所有维度数组修饰 X[n1][n2] -> X