本文将对一些常见c++关键字做一个总结,简单的一笔带过,复杂的会有详细的使用示例。
目录
一、C++11新增关键字
1. constexpr
constexpr可以修饰函数参数、函数返回值、变量、类的构造函数、函数模板等,是一种比const更加严格的约束,它修饰的表达式除了具有“运行时常量性”,也具有“编译时常量性”,即constexpr修饰的表达式的值在编译期间可知。详细使用参考:《Effective Modern C++》学习笔记之条款十五:只要有可能使用constexpr,就使用它_王木木-CSDN博客
2. decltype
decltype的作用是,以一个普通表达式作为参数,返回该表达式的类型,主要用在那些返回值依赖于形参型别的函数模板场景。详细使用参考:《Effective Modern C++》学习笔记之条款三:理解decltype_王木木-CSDN博客
3. final
使用final
关键字修饰的类,表示这个类不能够被继承,否则将会编译报错。
#include <iostream>
class A final{
};
// 编译报错,A不能被继承
class B : A {
};
4. override
在子类继承父类时,如果想要重写父类的虚函数,则可以在子类中重写的函数但后面使用override
关键字进行修饰,如果在子类的重写函数的签名写错,则会提示编译错误,避免一些低级错误出现。
include <iostream>
class A {
public:
virtual void func1(){}
};
class B : A {
public:
// 编译报错,父类中的func1函数签名与该函数签名不一致,无法完成覆盖
virtual void func1(int i) override {}
};
5. =delete
当为了不让一个类被拷贝,有两个方法可以完成:
- 将其拷贝构造函数声明为
private
属性 - 可以直接在拷贝构造函数的参数列表后面加上
=delete
所以如果你不想让编译器自动生成默认的构造函数,则可以在构造函数后面加上=delete
,这样编译器就会删除对应的默认构造函数了。
#include <iostream>
class CobjectA {
public:
CobjectA(int i) {};
CobjectA() = delete;
CobjectA(const CobjectA& c) = delete;
operator=(const CobjectA& c) = delete;
};
int main()
{
CobjectA Test; // 报错,默认构造函数被删除
CobjectA Test1(1);
CobjectA Test2 = Test1;// 报错,默认拷贝构造函数被删除
CobjectA Test3(3);
Test3 = Test1; // 报错,等号复制函数被删除
return 0;
}
详细使用说明,参考:《Effective Modern C++》学习笔记之条款十一:优先选用delete删除函数,而非private未定义函数_王木木-CSDN博客
6. =default
在C++11中,如果在已经自定义构造函数时,仍然想要编译器为我们生成默认的构造函数,则只需要在构造函数的参数列表后面加上=default
关键字,此时,即使我们自定义了构造函数,但编译器依然为我们生成默认构造函数:
#include <iostream>
class CobjectA {
public:
CobjectA(int i) {};
CobjectA() = default; // 提示编译器为该类生成默认构造函数
};
int main()
{
CobjectA Test; // 此时仍然可以调用默认构造函数
std::cout << "Test Con !" << std::endl;
return 0;
}
二、传统关键字
1. asm
asm (指令字符串):允许在 C++ 程序中嵌入汇编代码。
2. auto
auto C++98中表示自动变量,C++11中对其赋予新的特性,即修饰的变量类型自动推导,另外auto修饰的变量必须初始化。
int a = 10;
auto b = a; // b的类型同a为int
auto c = 10 / 3;// c的类型为float
auto d; //错误,auto变量必须初始化
3. bool
bool(布尔)类型,C++ 中的基本数据结构,其值可选为 true(真)或者 false(假)
4. break
break(中断、跳出),用在switch语句或者循环语句中。程序遇到 break 后,即跳过该程序段,继续后面的语句执行。
5. case
用于 switch 语句中,用于判断不同的条件类型。
6. catch
catch 和 try 语句一起用于异常处理。
7. char
char 字符类型,C++ 中的基本数据结构
8.class
class(类)是 C++ 面向对象设计的基础。使用 class 关键字声明一个类。
9. const
- 修饰变量时,表示其所修饰的变量不可更改。但如果是在全局作用域内声明的const变量,则表示的是该变量只在该文件内可见,如果外部文件要引用,则需要显示进行extern。
- 修饰类成员函数时,表示的是不能在该函数内修改任何成员变量,因为此时this指针将变为const(mutable修饰的变量除外)
注意:在类成员函数中,const关键字不能与static关键字同时使用,因为static函数是类的静态成员函数,静态成员函数不含有this指针
10. const_cast用法:
参考博客:C++进阶(六) :C++的四种强制类型转换_王木木-CSDN博客
11. continue
continue(继续)关键字用于循环结构。它使程序跳过代码段后部的部分,与 break 不同的是,它是"继续循环"之意,不是 break(跳出)。
12. default
default(默认、缺省),常用于 switch 语句,但也可以用于修饰类的默认构造函数,表示需要编译为我们生成默认构造函数。可以参考博客:C++进阶(二) : 构造函数与析构函数【详解】_王木木-CSDN博客
13. delete
delete(删除)释放程序动态申请的内存空间。delete 后面通常是一个指针或者数组 [],且只能 delete 通过 new 关键字申请的指针,否则会发生段错误。
14. do
do-while是一类循环结构。与while循环不同,do-while循环保证至少要进入循环体一次。
15. double
double(双精度)类型,C++ 中的基本数据结构,以双精度形式存储一个浮点数。
16. dynamic_cast
参考博客:C++的四种强制类型转换
17. else
else 紧跟在 if 后面,用于对 if 不成立的情况的选择。
18. enum
enum(枚举)类型,给出一系列固定的值,只能在这里面进行选择一个。
19. explicit
explicit(显式的)的作用是修饰类的构造函数以达到"禁止单参数构造函数"被用于自动型别转换目的
#include <iostream>
using namespace std;
// 未使用explicit 修饰
class Point {
public:
int x, y;
Point(int x = 0, int y = 0)
: x(x), y(y) {}
};
// 使用explicit 修饰
class Point2 {
public:
int x, y;
explicit Point2(int x = 0, int y = 0)
: x(x), y(y) {}
};
void displayPoint(const Point& p)
{
cout << "(" << p.x << ","
<< p.y << ")" << endl;
}
void displayPoint2(const Point2& p)
{
cout << "(" << p.x << ","
<< p.y << ")" << endl;
}
int main()
{
// 自动类型推导,将数字1推导为Point实例,进行参数调用
displayPoint(1);
// 自动类型推导,将数字2推导为Point实例
Point p = 2;
// 编译报错,禁止单参数类型推导
displayPoint2(1);
}
20. export
为了访问其他编译单元(如另一代码文件)中的变量或对象,对普通类型(包括基本数据类、结构和类),可以利用关键字 extern,来使用这些变量或对象时;但是对模板类型,则必须在定义这些模板类对象和模板函数时,使用标准 C++ 新增加的关键字 export(导出)。
21. extern
extern声明变量或函数为外部链接,提示编译器该变量或函数在其它文件中定义的。被其修饰的变量(外部变量)是全局变量或函数。
在 C++ 中,还可用来指定使用另一语言进行链接,这时需要与特定的转换符一起使用。目前仅支持 C 转换标记,来支持 C 编译器链接。使用这种情况有两种形式:
extern "C" 声明语句 extern "C" { 声明语句块 }
22. false
false(假的),C++ 的基本数据结构 bool 类型的值之一。等同于 int 的 0 值。
23. float
float(浮点数),C++ 中的基本数据结构,精度小于 double。
24. for
for 是 C++ 中的循环结构之一。
25. friend
friend(友元)声明友元关系。友元可以访问与其有 friend 关系的类中的 private/protected 成员,通过友元直接访问类中的 private/protected 成员的主要目的是提高效率。友元包括友元函数和友元类。
26. goto
goto(转到),用于无条件跳转到某一标号处开始执行,目前建议不再使用。
27. if
if(如果),C++ 中的条件语句之一,可以根据后面的 bool 类型的值选择进入一个分支执行。
28. inline
inline(内联)函数的定义将在编译时在调用处展开。inline定义的内联函数,函数代码被放入符号表中 ,效率会很高,但是inline 函数要求短小,且没有耗时操作。
29. int
int(整型,integer),C++ 中的基本数据结构,用于表示整数,精度小于 long。
30. long
long(长整型,long integer),C++ 中的基本数据结构,用于表示长整数。
31. mutable
如果一个类的成员函数被声明为 const 类型,表示在该函数内不可更改该类的成员变量,也就是该函数不会修改类的非静态数据成员。但是有些时候需要在该类函数中对类的数据成员进行赋值,这个时候就需要用到 mutable 关键字,被mutable修饰的变量可以在const函数内被修改:
class ClxTest
{
public :
ClxTest();
~ ClxTest();
int GetOutputTimes() const {
// 因为m_iTimes被mutable修饰,所以,即使在const函数中依然可以修改其值
m_iTimes = 2;
}
private :
mutable int m_iTimes;
};
另外,在 Lambda 表达式的设计中,当外部变量被按值捕获(Caputre by Value)的方式捕获时,是不允许程序员在 Lambda 函数的函数体中修改该变量的。而以 mutable
修饰 Lambda 函数,则可以打破这种限制。
int x{0};
auto f1 = [=]() mutable {x = 42;}; // okay, 创建了一个函数类型的实例
auto f2 = [=]() {x = 42;}; // error, 不允许修改按值捕获的外部变量的值
32. namespace
namespace(命名空间)用于在逻辑上组织类,是一种比类大的结构。
33. new
new(新建)用于新建一个对象。若创建失败,一般场景下会跑出异常,但如果使用std::nothrow修饰,则不会跑出异常,只会返回nullptr:
int* p = new (std::nothrow) int;
34. operator
operator(操作符)用于操作符重载。这是 C++ 中的一种特殊的函数。
35. private
private(私有的),C++ 中的访问控制符。被标明为 private 的字段只能在本类以及友元中访问。详细使用教程请参考博客:C++进阶(六) : 封装【详解】
36. protected
protected(受保护的),C++ 中的访问控制符。被标明为 protected 的字段只能在本类以及其继承类和友元中访问。 详细使用教程请参考博客:C++进阶(六) : 封装【详解】
37. public
public(公有的),C++ 中的访问控制符。被标明为 public 的字段可以在任何类。 详细使用教程请参考博客:C++进阶(六) : 封装【详解】
38.register
请求编译器尽可能将register修改但变量放到寄存器中,以提升效率,但register使用需要注意以下几点:
- register 变量必须是能被CPU 寄存器所接受的类型。意味着register 变量必须是一个单个的值,并且其长度应小于或等于整型的长度。
- 不能用取址运算符“&”来获取register 变量的地址
- 只有局部自动变量和形式参数可以作为寄存器变量,其它(如全局变量)不行
- 局部静态变量不能定义为寄存器变量
39. reinterpret_cast
参考博客:C++的四种强制类型转换
40. return
return(返回)用于在函数中返回值。程序在执行到 return 语句后立即返回,return 后面的语句无法执行到。
41. short
short(短整型,short integer),C++ 中的基本数据结构,用于表示整数,精度小于 int。
42. signed
signed(有符号),表明该类型是有符号数,和 unsigned 相反。数字类型(整型和浮点型)都可以用 signed 修饰。但默认就是 signed,所以一般不会显式使用。
43. sizeof
由于 C++ 每种类型的大小都是由编译器自行决定的,为了增加可移植性,可以用 sizeof 运算符获得该数据类型占用的字节数。
44. static
static 修饰不同类型变量会有不一样的属性:
- 修饰普通变量/函数:限定其作用范围在一个文件内,在其它文件中不可见,程序开始时分配空间,结束时释放空间,默认初始化为 0,使用时可改变其值。
- 修饰成员变量:静态成员变量,意味着它被该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见。类的静态成员变量必须在声明它的文件范围内进行初始化才能使用,private 类型的也不例外。
- 修饰成员函数:静态成员函数,静态成员函数只能访问类的静态成员。
45. static_cast
参考博客:C++的四种强制类型转换
46. struct
struct(结构)类型,类似于 class 关键字,与 C 语言兼容(class 关键字是不与 C 语言兼容的),可以实现面向对象程序设计,默认其成员为public。
47. switch
switch(转换)类似于 if-else-if 语句,是一种多分枝语句。它提供了一种简洁的书写,并且能够生成效率更好的代码。但是,switch 后面的判断只能是int(char也可以,但char本质上也是一种int类型)。switch 语句最后的 default 分支是可选的。
48. template
template(模板),C++ 中泛型机制的实现。
49. this
this 返回调用者本身的指针。
50. throw
throw(抛出)用于实现 C++ 的异常处理机制,可以通过 throw 关键字"抛出"一个异常。
51. true
true(真的),C++ 的基本数据结构 bool 类型的值之一。等同于 int 的非 0 值。
52. try
try(尝试)用于实现 C++ 的异常处理机制。可以在 try 中调用可能抛出异常的函数,然后在 try 后面的 catch 中捕获并进行处理。
53. typedef
typedef(类型定义,type define),其格式为:
typedef 类型 定义名;
类型说明定义了一个数据类型的新名字而不是定义一种新的数据类型。定义名表示这个类型的新名字。
54. typeid
指出指针或引用指向的对象的实际派生类型。
55. typename
typename(类型名字)关键字告诉编译器把一个特殊的名字解释成一个类型。在下列情况下必须对一个 name 使用 typename 关键字:
- 1. 一个唯一的name(可以作为类型理解),它嵌套在另一个类型中的。
- 2. 依赖于一个模板参数,就是说:模板参数在某种程度上包含这个name。当模板参数使编译器在指认一个类型时产生了误解。
56. union
union(联合),类似于 enum。不同的是 enum 实质上是 int 类型的,而 union 可以用于所有类型,并且其占用空间是随着实际类型大小变化的。
57. unsigned
unsigned(无符号),表明该类型是无符号数,和 signed 相反。
58. using
表明使用 namespace。
59. virtual
virtual(虚的),C++ 中用来实现多态机制。
60. void
void(空的),可以作为函数返回值,表明不返回任何数据;可以作为参数,表明没有参数传入(C++中不是必须的);可以作为指针使用。
61. volatile
volatile(不稳定的)声明一个变量是易变的,所以每次读取都会去内存中重新读取该值,而不是取相应的寄存器值,同样,他的性能会有所下降。声明时的语法如下:
int volatile nVint;
62. wchar_t
wchar_t 是宽字符类型,每个 wchar_t 类型占 2 个字节,16 位宽。汉字的表示就要用到 wchar_t。