【学习笔记】一文搞懂C++关键字

C++关键字一览表

C++系统中预定义的、在语言或编译系统的实现中具有特殊含义的单词:
C++关键字

按功能分类速记

与类有关:class, public, private, protected, explicit, dynamic_cast, frirnd, virtual, this
与数据类型、数值有关:auto, bool, char, double, enum, void, int,short, long, float,const, const_cast, true, false, signed,unsigned,static, volatile, wchar_t
与动态分配内存有关:new,delete
与循环结构有关:for, while, do
与条件结构有关:if, else, switch, case, default
与错误、异常有关:try, catch, throw
与终止有关:continue, break, return
与类型转换有关:const_cast, dynamic_cast,reinterpret_cast, static_cast
与模板有关:template, typename

各个C++关键字的作用及代码示例

下面按字母顺序介绍各个关键字功能,并用简单代码片段展示具体使用方法:

1. asm

asm(指令字符串):用于嵌入汇编语言代码,允许C++程序中嵌入汇编代码,以便直接访问底层硬件、执行特定的汇编指令序列或进行一些性能优化。

//关键字asm的一个使用代码示例
#include <iostream>
int main(){
	int x = 5;
	int y = 10;
	asm("add %1, %0" : "r" (x) : "r" (y));
	std::cout << "Result: " << X << std::endl;
	return 0;
}

在上述代码中,我们使用asm关键字将一条汇编指令嵌入到C++代码中。该汇编指令执行了将y的值加到x上的操作。在示例中,我们使用%0和%1作为占位符来表示x和y。

2. auto

auto(自动,automatic)是存储类型标识符,用于自动类型推断。它允许编译器根据初始值、上下文自动确定变量的类型,并将其替换为推断出的实际类型。

//关键字auto的一个使用代码示例
#include <iostream>
int main(){
	auto x = 10; //x被推断为int类型
	auto name = "John"; //name被推断为const car*类型
	auto pi = 3.14; //pi被推断为double类型
	std::cout << "x:" << x << std::endl;
	std::cout << "name:" << name << std::endl;
	std::cout << "pi:" << pi << std::endl;
	return 0;
}

在上述示例中,x被推断为int类型,name被推断为const char*类型,pi被推断为double类型。

3. bool

bool(布尔)类型,C++ 中的基本数据结构,其值可选为 true(真)或者 false(假)。C++ 中的 bool 类型可以和 int 混用,具体来说就是 0 代表 false,非 0 代表 true。bool 类型常用于条件判断和函数返回值。

//关键字bool的一个使用代码示例
#include <iostream>
int main(){
	bool isTrue = true;
	bool isFalse = false;
	if (isTrue) {
		std::cout << "It's true!" << std::endl;
	} else {
        std::cout << "It is false!" << std::endl;
    }
	if (!isFalse) {
       	std::cout << "It is not false!" << std::endl;
    }
    return 0;
}

在上述代码中,我们声明了两个bool类型的变量:isTrue和isFalse。根据变量的值,我们进行条件判断并输出相应的信息。

运行示例代码将会输出以下内容:

It is true!
It is not false!

4. break

break(中断、跳出),用在switch语句或者循环语句中。当break语句执行时,它会立即终止包含它的循环或switch语句的执行,并跳出循环或switch语句的代码块。程序将继续执行后面的代码。

//关键字break的一个使用代码示例
#include <iostream>
int main() {
	// 在for循环中使用break
    for (int i = 1; i <= 5; i++) {
        if (i == 3) {
            break;
        }
        std::cout << i << " ";
    }
    std::cout << std::endl;
	//在switch语句中使用break
    int x = 2;
    switch (x) {
        case 1:
            std::cout << "One" << std::endl;
            break;
        case 2:
            std::cout << "Two" << std::endl;
            break;
    }
    return 0;
}

在第一个示例中,for循环从1到5迭代,当i的值等于3时,执行了break语句,导致循环提前终止。因此,输出为1 2,表示在break语句执行之前,循环体中的两个数字被输出。

在第二个示例中,switch语句根据变量x的值进行匹配。由于x的值为2,case 2分支被执行,并输出"Two"。然后,由于在该分支的末尾执行了break语句,整个switch语句被终止。因此,输出为"Two"。

5. case

case用于在switch语句中指定不同情况。在switch语句中,可以使用多个case关键字来指定不同的情况。当switch表达式的值与某个case后面的常量或常量表达式匹配时,与该case关联的代码块将被执行。如果没有匹配的case,可以选择使用default关键字指定一个默认的代码块。

//关键字case的使用代码示例
#include <iostream>
int main() {
    int x = 2;
    switch (x) {
        case 1:
            std::cout << "One" << std::endl;
            break;
        case 2:
            std::cout << "Two" << std::endl;
            break;
        default:
            std::cout << "Other" << std::endl;
            break;
    }
    return 0;
}

在上述代码中,我们使用switch语句根据变量x的值来选择不同的情况。根据x的值,我们指定了两个不同的case,分别是1和2。此外,我们还使用了default关键字来指定一个默认的情况。运行示例代码将输出Two。

6. catch

catch 和 try 语句一起用于异常处理。

在C++中,可以使用try-catch语句块来捕获异常。try块中包含可能引发异常的代码,而catch块用于捕获并处理异常。当异常被抛出时,程序会跳转到与异常类型匹配的catch块,并执行相应的异常处理代码。

//关键字catch的一个使用代码示例
#include <iostream>
int main(){
	try{
		int dividend = 10;
		int divisor = 0;
		int result = dividend / divisor;
		std::cout << "Result: " << result << std::endl;
	} catch (std::exception& e) {
		std::cout << "Exception caught: " << e.what() <<std::endl;
	}
	return 0;
}

在上述代码中,我们将除法操作放在‘try’块中。由于除数‘divisor’的值为0,导致除法运算引发了一个异常。在‘catch’块中,我们捕获并处理了‘std::exception’类型的异常。通过调用‘e.what()’方法,我们可以获取异常对象的错误信息并输出。

运行示例代码将会输出以下内容:

Exception caught: std::exception

7. char

char(字符,character)类型,C++ 中的基本数据结构,其值一般为 0~255 的 int。这 256 个字符对应着 256 个 ASCII 码。char 类型的数据需要用单引号 ’ 括起来。

//关键字char的一个使用代码示例
#include <iostream>
int main() {
    char letter = 'A';
    char digit = '7';
    char symbol = '$';
    std::cout << "Letter: " << letter << std::endl;
    std::cout << "Digit: " << digit << std::endl;
    std::cout << "Symbol: " << symbol << std::endl;
    return 0;
}

在上述代码中,我们声明了三个char类型的变量:letter、digit和symbol,分别存储了一个字母、一个数字和一个符号。然后,我们使用std::cout输出这些字符的值。

运行示例代码将会输出以下内容:

Letter: A
Digit: 7
Symbol: $

char类型在处理字符数据时非常有用,可以用于存储和操作单个字符。它在字符串处理、字符匹配和文本处理等方面起着重要的作用。

8.class

class(类)是 C++ 面向对象设计的基础。使用 class 关键字声明一个类。

类是一种用户自定义的数据类型,用于封装数据和函数成员,形成一个独立的实体,用于表示某个概念、对象或实体的特征和行为。

//关键字class的一个使用代码示例
#include <iostream>
// 定义一个简单的类
class MyClass {
public:
    int myData;
    void printData() {
        std::cout << "Data: " << myData << std::endl;
    }
};
//主函数
int main() {
    // 创建类的对象
    MyClass obj;
    obj.myData = 42;
    // 调用类的成员函数
    obj.printData();
    return 0;
}

9. const

const(常量的,constant),用于声明常量。常量是指在程序运行过程中不可修改的值,其值在定义后不能被改变。常量可以用于变量、函数参数和函数返回类型等。

下面是一些常见的用法示例:

① 声明常量变量

const int MAX_VALUE = 100;
const double PI = 3.14159;

在上述代码中,我们使用const关键字声明了两个常量变量,分别是MAX_VALUE和PI。这些常量的值在定义后不能被修改。

② 声明常量指针

const int* ptr = &MAX_VALUE;

在上述代码中,我们声明了一个指向整型常量的指针ptr。通过在int前加上const关键字,我们将指针指向的值声明为常量,从而不能通过该指针修改其指向的值。

③声明常量引用

const int& ref = MAX_VALUE;

在上述代码中,我们声明了一个对整型常量的引用ref。通过在引用类型前加上const关键字,我们将引用指向的值声明为常量,从而不能通过该引用修改其引用的值。

④ 声明常量成员函数

当const关键字用于修饰函数时,它表明该函数是一个常量成员函数。常量成员函数承诺不会修改类的成员变量,因此在函数体内不能修改类的数据成员。在函数的声明与定义时都要加上const,放在函数参数列表的最后一个括号后。

class MyClass {
private:
    int myData;
public:
    // 常量成员函数,不修改数据成员
    void printData() const {
        // myData = 10;  // 错误,常量成员函数不能修改成员变量
        std::cout << "Data: " << myData << std::endl;
    }    
    // 非常量成员函数,可以修改数据成员
    void setData(int value) {
        myData = value;
    }
};

int main() {
    const MyClass obj;
    obj.printData();  // 可以调用常量成员函数
    // obj.setData(10);  // 错误,常量对象不能调用非常量成员函数
    return 0;
}

在上述代码中,我们定义了一个类MyClass,其中包含了一个常量成员函数printData和一个非常量成员函数setData。在常量成员函数中,我们不能修改类的成员变量,因此尝试修改myData会导致编译错误。而在非常量成员函数中,我们可以修改类的成员变量。

在main函数中,我们创建了一个常量对象obj,并调用了它的常量成员函数printData。但是,我们不能使用常量对象调用非常量成员函数setData,因为常量对象不能修改其状态。

使用const修饰函数可以提供额外的类型安全和编译器检查,确保不会在常量对象上执行修改操作,并帮助开发人员编写更健壮的代码。

10. const_cast:

const_cast是C++中的一个运算符,用于移除变量的const属性,以便进行类型转换或修改const变量。
const_cast的用法如下为const_cast<type>(expression),其中,'type’表示要转换成的类型,'expression’表示要进行转换的表达式。 type 和 expression 的类型是一样的。

// 关键字const_cast的两个常见用例————

// 1. 将const指针转换为非const指针:
const int* ptr1 = new int(10);
int* ptr2 = const_cast<int*>(ptr1);
*ptr2 = 20; // 可以修改指针指向的值

// 2. 将const对象传递给接受非const引用参数的函数:
void modifyValue(int& value){
	value = 100;
}
const int num = 50;
modifyValue(const_cast<int&>(num)); //修改常量对象的值

在上述代码中,

  1. ptr1是一个指向const int的常量指针。使用const_cast将其转换为非const指针ptr2后,就可以通过ptr2修改指针指向的值。
  2. modifyValue函数接受一个非const引用参数。通过使用const_cast将num的const属性移除,我们可以将其传递给modifyValue函数,并在函数内部修改num的值。

需要注意的是,使用const_cast来移除const属性并修改const对象是一种非常规的操作,需要小心使用。修改一个本来应该是常量的对象可能会导致未定义的行为,因此在使用const_cast时应该确保不会引发潜在的错误。

11. continue

continue(继续)关键字用于在循环语句中跳过当前迭代并进入下一次迭代。它使程序跳过代码段后部的部分,与 break 不同的是,continue 不是进入代码段后的部分执行,而是重新开始新的循环。因而它是"继续循环"之意,不是 break(跳出)。

//关键字break的一个使用代码示例
#include <iostream>
int main(){
	for (int i = 1; i <= 5; i++){
		if (i ==3) {
			continue;
		}
		std::cout << i << " ";
	}
	return 0;
}

在上述代码中,我们使用for循环打印数字1到5,但当i等于3时,使用continue关键字跳过当前迭代。因此,在循环中执行到i等于3时,程序会直接进入下一次迭代,跳过了输出语句。

运行示例代码的输出将会是:

1 2 4 5

12. default

default(默认、缺省)用于在switch语句中定义默认情况下的操作。在switch语句中,可以使用多个case来匹配不同的值,并为每个匹配的情况执行相应的操作。然而,如果没有任何一个case与给定的值匹配,那么可以使用default关键字指定一个默认的操作。

代码示例详见“5 case“。

13. delete

delete(删除)用于释放由new关键字分配的动态内存或销毁对象。在C++中,通过使用new关键字可以动态地分配内存来创建对象或数组。当不再需要这些动态分配的内存或对象时,应使用delete关键字来显式释放内存或销毁对象,以防止内存泄漏和资源浪费。

// 关键字delete的两种常见用法

// 1. 释放单个对象:
int* ptr = new int; // 使用ptr指向的内存
delete ptr; // 释放内存

// 2. 销毁对象数组
MyClass* arr = new MyClass[5]; //使用arr指向的对象数组
delete[] arr; //销毁对象数组

在上述代码中,

  1. 通过new关键字分配了一个int类型的内存,并将其地址赋值给指针ptr。在使用完指针指向的内存后,使用delete关键字释放内存,以便其它部分可以重新使用这块内存。
  2. 通过new关键字分配了一个包含5个MyClass对象的对象数组,并将其地址赋值给指针arr。在使用完对象数组后,使用delete[]关键字销毁对象数组,以便对象的析构函数得到调用,并释放内存。

14. do

do用于定义一个do-while循环,也被称为后测试循环。与while循环不同,do-while循环是一种先执行循环体,然后再检查循环条件的循环结构,所以保证至少要进入循环体一次。它的语法如下:

do {
	//循环体
} while (condition);

首先,循环体会被执行一次,然后才会检查循环条件。如果循环条件为真(true),则继续执行循环体,直到循环条件为假(false)时才退出循环。

以下是一个示例代码,演示了do-while循环的使用:

#include <iostream>
int main() {
    int count = 0;
    do {
        std::cout << "Count: " << count << std::endl;
        count++;
    } while (count < 5);
    return 0;
}

在上述代码中,我们使用一个计数器变量count,并使用do-while循环输出计数器的值。循环体中首先输出计数器的值,然后将计数器加1。循环条件检查计数器是否小于5,如果满足条件则继续执行循环体,直到计数器达到5时退出循环。

运行示例代码的输出将会是:

Count: 0
Count: 1
Count: 2
Count: 3
Count: 4

15. double

double(双精度)类型,C++ 中的基本数据结构,以双精度形式存储一个浮点数。相比于float类型,double类型可以提供更大的位数来表示小数点前后的数字。

#include <iostream>
int main() {
    double pi = 3.14159;
    double radius = 2.5;
    double area = pi * radius * radius;
    std::cout << "The area of the circle is: " << area << std::endl;
    return 0;
}

在上述代码中,我们声明了三个double类型的变量:pi、radius和area。pi用于存储圆周率的近似值,radius用于存储圆的半径,area用于存储计算得到的圆的面积。通过使用这些变量,我们计算了圆的面积,并将结果输出到标准输出流。

运行示例代码的输出将会是:

The area of the circle is: 19.6349

16. dynamic_cast

dynamic_cast(动态转换),用于在运行时进行类型转换和多态对象的指针或引用的安全向下转型。

在面向对象编程中,当使用多态性(polymorphism)时,基类指针或引用可能指向派生类对象。在某些情况下,我们可能需要将基类指针或引用转换回派生类指针或引用,以便使用派生类特有的成员或方法。

dynamic_cast提供了一种安全的转型机制,用于将基类指针或引用转换为派生类指针或引用。它会在运行时进行类型检查,并确保转型是有效和安全的。如果转型不可行,dynamic_cast会返回空指针(对于指针转型)或抛出std::bad_cast异常(对于引用转型)。

// 关键字dynamic_cast的使用代码示例
#include <iostream>
// 定义一个基类
class Base {
public:
	virtual void print() {
		std::cout << "This is the Base class" << std::endl;
	}
};
// 定义一个派生类
class Derived :public Base {
public:
	void print() override {
		std::cout << "This is the Derived class" << std::endl;
	}
	void specificFunction() {
		std::cout << "This is a specific function of the Derived class" << std::endl;
	}
};

int main(){
	// 实际上,dynamic_cast提供了三种转换方式:
	
	// 1. 将基类指针转换为派生类指针
	Base* basePtr = new Derived;
	Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
	if (derivedPtr) {
		derivedPtr->print(); // 调用Derived类的print函数
		derivedPtr->specidicFunction(); // 调用Derived类特有的函数
	} else {
		std::cout << "Failed to perform dynamic_cast" << std::endl;
	}
	delete basePtr;
	
	// 2. 将基类引用转换为派生类引用
	Base& baseRef = someDerivedObject;
	try {
		Derived& derivedRef = dynamic_cast(Derived&)(baseRef);
		// 转换成功,可以使用derivesRef引用派生类对象
	} catch (std:bad_cast& e) {
		// 转换失败,处理异常
	}
	
	// 3.将基类指针转换成派生类引用
	Base* basePtr2 = new Derived2;
	try {
		Derived& derivedRef2 = dynamic_cast<Derived&>(*basePtr2);
		// 转换成功,可以使用derivedRef引用派生类对象
	} catch (std::bas_cast& e) {
		// 转换失败,处理异常
	}

	return 0;
}

在上述代码中,我们定义了一个基类Base和一个派生类Derived。在main函数中,

  1. 我们创建了一个基类指针basePtr并将其指向一个Derived类的对象。然后,使用dynamic_cast将基类指针转换为派生类指针derivedPtr。如果转换成功,我们可以使用derivedPtr调用派生类的成员函数,包括特有的函数specificFunction。如果转换失败,dynamic_cast将返回空指针,并在该分支中输出一条失败的消息。
  2. 我们创建了一个基类引用baseRef。然后,使用dynamic_cast将基类引用baseRef转换为派生类引用derivedRef。如果转换成功,则可以使用derivedRef引用派生类对象;如果转换失败,则会抛出std::bad_cast异常。
  3. 首先通过解引用操作符*将基类指针basePtr转换为基类引用,然后再使用dynamic_cast将基类引用转换为派生类引用derivedRef。如果转换成功,则可以使用derivedRef引用派生类对象;如果转换失败,则会抛出std::bad_cast异常。

需要注意的是,dynamic_cast只能用于具有多态性的类层次结构中,即基类必须至少有一个虚函数。此外,它只能用于指定型转换,无法用于转换非指针或非引用类型。另外,dynamic_cast的转型目标类型必须是完整的类类型,不能是抽象类或非完整类型。

17. else

else 紧跟在 if 后面,用于在条件语句中指定当条件不满足时要执行的代码块。

// 关键字else的一个代码示例
#include <iostream>
int main() {
	int num =5;
	if (num >10) {
		std::cout << "num 大于 10" << std::endl;
	} else {
		std::cout << "num 小于等于 10" << std::endl;
	}
	return 0;
}

输出结果:

num 小于等于 10

18. enum

enum(枚举)类型,给出一系列固定的值,只能在这里面进行选择一个。枚举类型是一种用户自定义的数据类型,它用于定义一组具名的常量值,这些常量值称为枚举成员。

// 关键字enum的一个代码示例
#include <iostream>

enum Day {
	Monday, //默认值为0
	Tuesday, //默认值为1
    Wednesday, //默认值为2
    Thursday, //默认值为3
    Friday, //默认值为4
    Saturday, //默认值为5
    Sunday //默认值为6
};

int main() {
	Day today = Tuesday;
	if (today == Saturday || today == Sunday) {
		std::cout << "今天是周末!" << std::endl;
    } else {
        std::cout << "今天是工作日。" << std::endl;
    }
    return 0;
}

在上述代码中,我们定义了一个枚举类型 Day,其中包含了一组枚举成员 Monday、Tuesday、Wednesday、Thursday、Friday、Saturday 和 Sunday。这些枚举成员都被赋予了默认的整数值,从0开始依次递增。

运行代码得到输出结果:

今天是工作日

枚举类型的枚举成员默认情况下是从0开始递增的整数值。但是,我们也可以手动为枚举成员指定特定的值。这在与外部系统进行交互或处理特定状态码时特别有用。

enum Status {
    OK = 200,        // 值为200
    BadRequest = 400 // 值为400
};

请注意,虽然我们可以为枚举成员指定特定值,但枚举成员仍然是常量,不能在程序运行时修改。它们代表了一组固定的常量值。

19. explicit

explicit(显式的),用于修饰类的构造函数。它的作用是防止编译器进行隐式的类型转换,要求显式地调用构造函数来完成对象的创建。

// 关键字explicit的一个使用代码示例
#include <iostream>

class MyClass {
public:
	// 用explicit修饰MyClass的构造函数
	// 构造函数(Constructor)是一种特殊的成员函数,用于初始化类的对象。它具有与类名称相同的名称,并且在对象被创建时自动调用。
	// 使用成员初始化列表(Member Initialization List)来对成员变量进行初始化。成员初始化列表位于构造函数的参数列表之后,在冒号 : 后面。
    explicit MyClass(int value) : data(value) {}
    int getData() const {
        return data;
    }
private:
    int data;
};

void printData(const MyClass& obj) {
    std::cout << "Data: " << obj.getData() << std::endl;
}

int main() {
    MyClass obj1(10);     // 直接调用构造函数进行对象的创建
    printData(obj1);
    MyClass obj2 = 20;    // 编译错误:禁止隐式的类型转换
    printData(obj2);
    return 0;
}

在上述代码中,我们定义了一个 MyClass 类,它具有一个带有 int 参数的构造函数。通过在构造函数前加上 explicit 关键字,我们告诉编译器禁止隐式的类型转换。

在 main 函数中,我们首先直接调用构造函数 MyClass obj1(10) 来创建一个 MyClass 对象,并将其传递给 printData 函数进行打印。

然而,当我们尝试使用 MyClass obj2 = 20 进行对象的初始化时,编译器会产生错误。这是因为我们禁止了隐式的类型转换,要求显式地调用构造函数来创建对象。如果我们想正确创建 obj2,可以修改为 MyClass obj2(20)。

通过使用 explicit 关键字,我们可以避免编译器进行隐式的类型转换,增强代码的可读性和安全性。

20. export

为了访问其他编译单元(如另一代码文件)中的变量或对象,对普通类型(包括基本数据类、结构和类),可以利用关键字 extern,来使用这些变量或对象时;但是对模板类型,则必须在定义这些模板类对象和模板函数时,使用标准 C++ 新增加的关键字 export(导出)。尽管 export 关键字在 C++ 中存在,但在实际开发中并不常用,并且未来可能会被移除。因此,目前不建议使用 export 关键字。

21. extern

extern(外部的)声明外部变量或函数,指示编译器在其他文件中寻找它们的定义。

在 C++ 中,如果需要在一个源文件中引用另一个源文件中定义的全局变量或函数,我们可以使用 extern 关键字在当前源文件中声明该变量或函数。这样编译器就知道这个变量或函数是在其他地方定义的,并会在链接阶段将它们正确地连接起来。

main.cpp:

#include <iostream>
extern int globalVariable; // 声明外部变量
extern void externalFunction(); // 声明外部函数
int main() {
    std::cout << "Accessing global variable: " << globalVariable << std::endl;
    externalFunction();
    return 0;
}

other.cpp:

#include <iostream>
// 定义外部变量
int globalVariable = 42; 
// 定义外部函数
void externalFunction() {
    std::cout << "Calling external function" << std::endl;
}

输出结果:

Accessing global variable: 42
Calling external function

在上述代码中,main.cpp 文件中使用 extern 关键字声明了一个外部变量 globalVariable 和一个外部函数 externalFunction。这样编译器就知道它们是在其他文件中定义的,并在链接阶段进行连接。

other.cpp 文件中定义了实际的外部变量 globalVariable 和外部函数 externalFunction。在 main 函数中,我们可以访问外部变量并调用外部函数,输出相应的结果。

通过使用 extern 关键字,我们可以在不同的源文件中共享全局变量和函数,实现模块化和代码重用。

在 C++ 中,还可用来指定使用另一语言进行链接,这时需要与特定的转换符一起使用。目前仅支持 C 转换标记,来支持 C 编译器链接。

代码示例:

c_code.c:

//这是一个名为 c_code.c 的 C 文件,其中定义了一个 cFunction 函数
#include <stdio.h>
void cFunction() {
    printf("C Function\n");
}

cpp_code.cpp:

// 这是用extern "C" {语句块} 声明用C语言进行链接的cpp代码
#include <iostream>

extern "C" {
    void cFunction(); // 使用 extern "C" 声明 C 函数
}

int main() {
    std::cout << "Calling C function: ";
    cFunction(); // 调用 C 函数
    return 0;
}

输出结果:

Calling C function: C Function

在 main 函数中,我们调用了 cFunction 函数,它实际上是在 C 文件中定义的函数。通过使用 extern “C”,我们可以在 C++ 代码中调用 C 代码,实现了 C++ 与 C 的混合编程。

22. false

false(假的),C++ 的基本数据结构 bool 类型的假值。等同于 int 的 0 值。示例代码同关键字bool。

23. float

float(浮点数),C++ 中的基本数据结构,用于声明单精度浮点数类型,精度小于 double。

// 关键字float的一个代码示例
#include <iostream>
int main() {
    // 定义一个单精度浮点数类型的变量
    //注意,在初始化浮点数时,需要在数值后面添加 f 后缀,以明确指示该值是 float 类型而不是 double 类型。
    float floatValue = 3.14f; 
    std::cout << "Float value: " << floatValue << std::endl;
    return 0;
}

输出结果为:

Float value: 3.14

24. for

for 是 C++ 中的循环结构之一。for 循环通常由三个部分组成:

  1. 初始化部分:在循环开始之前执行一次,用于初始化循环变量或设置初始条件。
  2. 循环条件部分:在每次循环开始之前进行判断,如果条件为真,则执行循环体内的代码块,否则跳出循环。
  3. 迭代部分:在每次循环结束后执行,用于更新循环变量的值或调整迭代条件。
#include <iostream>
int main() {
    for (int i = 0; i < 5; i++) {
    // 初始化部分:int i = 0;
    // 循环条件部分: i < 5;
    // 迭代部分: i++
        std::cout << "Iteration: " << i << std::endl;
    }
    return 0;
}

25. friend

friend(友元)声明友元关系。友元可以访问与其有 friend 关系的类中的 private/protected 成员,通过友元直接访问类中的 private/protected 成员的主要目的是提高效率。友元包括友元函数和友元类。

#include <iostream>

class MyClass {
private:
    int privateData; //私有成员变量 privateData

public:
    MyClass(int data) : privateData(data) {}
	// 使用 friend 关键字将 friendFunction 声明为 MyClass 的友元函数。
    friend void friendFunction(MyClass& obj);
};
// 在友元函数中,可以直接访问 MyClass 的私有成员 privateData,并将其输出
void friendFunction(MyClass& obj) {
    std::cout << "Accessing private data from friend function: " << obj.privateData << std::endl;
}

int main() {
    MyClass myObj(42);
    // 调用友元函数
    friendFunction(myObj);
    return 0;
}

输出结果:

Accessing private data from friend function: 42

通过使用 friend 关键字,我们可以在需要的情况下,允许其他类或函数访问类的私有成员,以实现更灵活的访问控制。需要注意的是,过度使用友元关系可能导致破坏封装性和增加代码耦合度,应谨慎使用。

26. goto

goto(转到),用于无条件跳转到某一标号处开始执行。

// 关键字goto的一个代码示例
#include <iostream>
int main() {
    int number = 1;
    repeat:  //定义了一个标签repeat
    std::cout << "Number: " << number << std::endl;
    number++;
    if (number <= 5) {
        goto repeat; //如果 number 小于等于 5,则跳转到标记 repeat 处继续执行,否则跳出循环。
    }
    return 0;
}

goto 语句可以用于跳过当前执行位置,并直接转移到代码中指定的标记处继续执行。它是一种流程控制语句,但由于它容易导致程序结构混乱,使代码难以理解和维护,通常不推荐频繁使用。

27. if

if(如果),C++ 中的条件语句之一,可以根据后面的 bool 类型的值选择进入一个分支执行。如果条件为真(非零),则执行 if 代码块中的语句;如果条件为假(零),则跳过 if 代码块。

// 关键字if的一个代码示例
#include <iostream>
int main() {
    int number = 42;
    if (number > 0) {
        std::cout << "Number is positive." << std::endl;
    } else {
        std::cout << "Number is non-positive." << std::endl;
    }
    return 0;
}

28. inline

inline(内联)用于对函数进行内联(inline)展开。它是一种优化技术,可以减少函数调用的开销,并提高程序的执行效率。

使用 inline 关键字可以建议编译器在函数调用的地方直接展开函数体,而不是通过跳转到函数定义的地址执行函数。这样可以避免函数调用时的开销,如栈帧的创建和销毁,参数的传递等,从而减少程序的运行时间。

// 关键字inline的一个代码示例
#include <iostream>
//使用 inline 关键字定义了一个名为 add 的内联函数。
inline int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(5, 3); //由于 add 函数被声明为内联函数,编译器会尝试在函数调用的地方直接展开函数体,从而避免了函数调用的开销。
    std::cout << "Result: " << result << std::endl;
    return 0;
}

通过使用 inline 关键字,我们可以优化函数调用,提高程序的执行效率。需要注意的是,对于较大的函数或频繁调用的函数,编译器可能会选择不进行内联展开,而是按照普通函数进行处理。因此,inline 关键字仅提供了对编译器的建议,实际是否内联展开取决于编译器的决策。

29. int

int(整型,integer),C++ 中的基本数据结构,用于表示整数,它通常用于存储整数数据,可以表示正数、负数和零,精度小于 long。示例代码略。

30. long

long(长整型,long integer),C++ 中的基本数据结构,用于表示长整数,比 int 类型所能表示的范围更广。一般情况下,long 类型的变量至少占用 4 个字节的存储空间,但也可能更多。在需要存储更大范围的整数时,可以使用 long long 类型(超过8个字节的储存空间)或其他更大的整数类型。

31. mutable

mutable(易变的)是 C++ 中一个不常用的关键字,用于声明类的成员变量为可变的。只能用于类的非静态和非常量数据成员。由于一个对象的状态由该对象的非静态数据成员决定,所以随着数据成员的改变,对像的状态也会随之发生变化。如果一个类的成员函数被声明为 const 类型,表示该函数不会改变对象的状态,也就是该函数不会修改类的非静态数据成员。但是有些时候需要在该类函数中对类的数据成员进行赋值,这个时候就需要用到 mutable 关键字。

// 关键字mutable的一个使用代码示例
#include <iostream>

class Counter {
public:
    Counter() : count(0), mutableCount(0) {}
    int getCount() const {
        ++mutableCount; // 常量成员函数可以对可变成员变量进行修改操作
        return  mutableCount;
    }
private:
    int count;
    mutable int mutableCount; // 声明整型成员变量mulableCount可变
};

int main() {
    Counter c;
    std::cout << "Modified Mutable Count: " << c.getCount() << std::endl;
    return 0;
}

输出结果:

Modified Mutable Count: 1

32. namespace

namespace(命名空间)用于在逻辑上组织类,是一种比类大的结构。用于创建命名空间(namespace),用于将一组相关的名称(变量、函数、类等)组织在一起,以避免命名冲突。

#include <iostream>
// 命名空间 A
namespace A {
    void greet() {
        std::cout << "Hello from namespace A!" << std::endl;
    }
}
// 命名空间 B
namespace B {
    void greet() {
        std::cout << "Hello from namespace B!" << std::endl;
    }
}
int main() {
    A::greet(); // 调用命名空间 A 中的 greet 函数
    B::greet(); // 调用命名空间 B 中的 greet 函数
    return 0;
}

输出结果:

Hello from namespace A!
Hello from namespace B!

通过使用命名空间,我们可以将具有相同名称的函数(或其他名称)组织到不同的命名空间中,避免命名冲突。这在大型项目中特别有用,可以更好地组织和管理代码。

命名空间可以嵌套,允许创建更复杂的命名空间层次结构。同时,命名空间也可以使用别名来简化使用,以及通过 using 关键字引入整个命名空间或特定的成员。

33. new

new(新建)用于在堆上动态分配内存来创建对象或数组。它与 delete 关键字配合使用,用于释放通过 new 分配的内存。new 运算符总是返回一个指针。

// 关键词new的一个代码示例
#include <iostream>

int main() {
    // 动态分配单个整数对象
    int* ptr = new int;
    *ptr = 10;
    std::cout << "Value: " << *ptr << std::endl;
    // 动态分配整数数组
    int size = 5;
    int* arr = new int[size];
    for (int i = 0; i < size; ++i) {
        arr[i] = i + 1;
    }
    std::cout << "Array:";
    for (int i = 0; i < size; ++i) {
        std::cout << " " << arr[i];
    }
    std::cout << std::endl;
    // 释放动态分配的内存
    delete ptr;
    delete[] arr;
    return 0;
}

输出结果:

Value: 10
Array: 1 2 3 4 5

使用 new 和 delete 的正确配对是非常重要的,否则可能导致内存泄漏或其他内存错误。

34. operator

operator(操作符)用于操作符重载。这是 C++ 中的一种特殊的函数,可以定义自定义类型的运算符行为,使其可以像内置类型一样进行运算。C++ 中提供了一系列的运算符可以进行重载,如算术运算符、比较运算符、位运算符等。

// 关键字operator的一个使用代码示例
#include <iostream>
class Vector2D {
public:
	Vector(double x = 0.0, double y = 0.0) : m_x(x), m_y(y) {}
	// 重载加法运算符 +
	Vector2D operator+(const Vector2D& other) const {
		return Vector2D(m_x + other.m_x, m_y + other.m_y);
	}
	// 重载乘法运算符 *
	Vector2D operator*(double scalar) const {
		return Vector2D(m_x * scalar, m_y *scalar);
	}
	// 重载输出流运算符 <<
	friend std::ostream& operator<<(std::ostream& os, const Vector2D& vec) {
		os << "(" << vec.m_x << "," << vec.m_y << ")";
		return os;
	}
private:
	double m_x;
	double m_y;
};

int main() {
	Vector2D v1(2.0, 3.0);
	Vector2D v2(1.0, 2.0);
	// 使用重载的加法运算符 +
	Vector2D sum = v1 + v2;
	std::cout << "Sum:" << scaled << std::endl;
	// 使用重载的加法运算符 +
	Vector2D scaled = v1 * 2.5;
	std::cout << "Scaled:" << scaled << std::endl;
	return 0;
}	

输出结果:

Sum: (3, 5)
Scaled: (5, 7.5)

35. private

private(私有的),C++ 中的访问控制符,用于声明类的私有成员。被标明为 private 的字段只能在本类以及友元中访问。在类的定义中,成员变量和成员函数的默认访问权限是 private。因此,如果没有显式指定成员的访问权限,它们将被视为 private 成员。

// 关键字private的一个代码示例
#include <iostream>

class MyClass {
public:
    void publicMethod() {
        std::cout << "Public method" << std::endl;
    }
private:
    int privateData;
    void privateMethod() {
        std::cout << "Private method" << std::endl;
    }
};

int main() {
    MyClass obj;
    obj.publicMethod();   // 可以调用公有成员函数
    //obj.privateData;    // 错误:无法访问私有成员变量
    //obj.privateMethod(); // 错误:无法调用私有成员函数
    return 0;
}

输出结果:

Public method

在上述代码中,MyClass 类具有一个公有成员函数 publicMethod 和一个私有成员变量 privateData 以及一个私有成员函数 privateMethod。

在 main 函数中,我们创建了一个 MyClass 对象 obj,并调用了公有成员函数 publicMethod,输出相应的内容。但是,我们无法直接访问私有成员变量 privateData 或调用私有成员函数 privateMethod,因为它们的访问权限是 private。

通过将成员变量声明为 private,我们可以封装类的内部实现细节,从而提供更好的数据隐藏和封装性。私有成员只能在类的内部进行操作,可以有效地控制成员的访问和使用范围

36. protected

protected(受保护的),C++ 中的访问控制符,用于声明类的受保护成员。受保护成员在类的内部和派生类中可访问,但不能从类的外部直接访问。

与 private 成员不同,protected 成员可以被派生类访问。这使得派生类能够继承和使用基类的受保护成员,从而实现类之间的继承关系和数据共享。

#include <iostream>

class MyBaseClass {
protected:
    int protectedData;
    void protectedMethod() {
        std::cout << "Protected method" << std::endl;
    }
};

class MyDerivedClass : public MyBaseClass {
public:
    void accessProtectedMember() {
        protectedData = 42;              // 可以访问基类的受保护成员变量
        std::cout << protectedData << std::endl;
        protectedMethod();               // 可以调用基类的受保护成员函数
    }
};

int main() {
    MyDerivedClass obj;
    obj.accessProtectedMember();
    return 0;
}

输出结果:

42
Protected method

37. public

public(公有的),C++ 中的访问控制符,用于声明类的公有成员。公有成员可以在类的内部、派生类和类的外部访问。

#include <iostream>

class MyClass {
public:
	// 公有成员变量
    int publicData;
	// 公有成员函数
    void publicMethod() {
        std::cout << "Public method" << std::endl;
    }
};

int main() {
    MyClass obj;
    obj.publicData = 42;          // 可以直接访问公有成员变量
    std::cout << obj.publicData << std::endl;

    obj.publicMethod();           // 可以调用公有成员函数

    return 0;
}

公有成员在类的接口中起着重要的作用,可以被类的使用者直接访问和操作。它们定义了类的行为和功能,并提供了对外部代码的接口。

38. register

register(寄存器)用于向编译器建议将变量存储在寄存器中,以便提高访问速度。

在使用 register 关键字时,我们告诉编译器将变量存储在寄存器中,而不是内存中。这样可以加快对变量的访问速度,因为寄存器通常比内存更快。但请注意,register 关键字只是向编译器提供一个建议,而不是强制要求。编译器可以选择忽略这个建议,并将变量存储在内存中。

需要注意以下几点:

  1. register 关键字只能应用于自动变量(在函数内部声明的变量)和函数参数,不能用于全局变量或静态变量。
  2. 变量的类型必须是可寄存器的,即不能是引用类型或具有 volatile 限定符的类型。
  3. register 关键字不能与 static、extern 或 mutable 关键字一起使用。
//关键字register的一个代码示例
register int x;

上述代码将 x 声明为一个寄存器变量,该变量将尽可能地存储在CPU寄存器中。然而,编译器可以忽略 register 关键字,将变量存储在内存中,因为现代编译器对变量的优化能力很强,它们能够根据上下文和优化策略决定变量的存储位置

39. reinterpret_cast

reinterpret_cast 是 C++ 中的一种类型转换运算符,用于进行不安全的类型转换。它可以将一个指针或引用类型转换为不同类型的指针或引用,甚至可以将一个整数类型转换为指针类型,或者将一个指针类型转换为整数类型。

reinterpret_cast 的语法如下:

reinterpret_cast<new_type>(expression)

new_type是欲转换的目标类型,必须是一个指针、引用、算术类型、函数指针或者成员指针。expression 是需要进行转换的表达式。

// 关键字reinerpret_cast的三个使用示例
// 示例1:将一个整数转换为指针
int num = 42;
int* ptr = reinterpret_cast<int*>(num);

// 示例2:将一个指针类型转换为整数
int* p = new int(10);
uintptr_t value = reinterpret_cast<uintptr_t>(p);

// 示例3:将一个基类指针转换为派生类指针(潜在的危险操作)
class Base {
    // ...
};
class Derived : public Base {
    // ...
};

Base* basePtr = new Derived();
Derived* derivedPtr = reinterpret_cast<Derived*>(basePtr); //这里实现的功能与dynamic_cast作用相似,但是dynamic_cast更安全

需要谨慎使用 reinterpret_cast,并确保你了解这种类型转换的潜在风险和后果。通常情况下,应优先考虑使用更安全和类型安全的转换方式,如 static_cast、dynamic_cast 或 const_cast,这些转换运算符提供了更严格的类型检查和更明确的语义。

40. return

return(返回)用于在函数中返回值。程序在执行到 return 语句后立即返回,return 后面的语句无法执行到。

在函数中,可以使用 return 关键字来返回一个值。函数的返回类型在函数声明或定义时指定,而 return 关键字后面的表达式的类型必须与返回类型匹配。如果函数的返回类型是 void,则可以省略 return 关键字或只使用 return; 来表示函数的结束。

41. short

short(短整型,short integer),C++ 中的基本数据结构,用于表示短整数(通常为16位),精度小于 int。它可以用来存储较小的整数值,节省内存空间。

// 关键字short的一个代码示例
short num1 = 42;
short num2 = -100;
short num3 = 0;

// 进行算术运算
short sum = num1 + num2;
short difference = num1 - num2;
short product = num1 * num2;
short quotient = num1 / num2;

short 的完整声明是 short int,但通常可以简写为 short。它是有符号类型,可以表示正数、负数和零。在大多数系统中,short 的范围是从 -32,768 到 32,767。对于需要更大范围的整数值,可以考虑使用 int 或其他适合的整数类型。

42. signed

signed(有符号),表明该类型是有符号数,和 unsigned 相反。数字类型(整型和浮点型)都可以用 signed 修饰。但默认就是 signed,所以一般不会显式使用。

// 关键字signed的一个代码示例
signed int num1 = -10;
signed short num2 = 100;
signed long num3 = -123456789;

43. sizeof

由于 C++ 每种类型的大小都是由编译器自行决定的,为了增加可移植性,可以用 sizeof 运算符获得该数据类型占用的字节数,它返回一个 size_t 类型的值。它是在编译时求值的,因此不会对对象进行实际的计算或调用构造函数。

// 关键字sizeof的代码示例
int num = 42;
std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl; //sizeof(int)求的是所有int类型所占空间的字符数
std::cout << "Size of num: " << sizeof(num) << " bytes" << std::endl; //sizeof(num)求的是num这个变量所占空间的字符数

double pi = 3.14159;
std::cout << "Size of double: " << sizeof(double) << " bytes" << std::endl;
std::cout << "Size of pi: " << sizeof(pi) << " bytes" << std::endl;

struct Point {
    int x;
    int y;
};
std::cout << "Size of Point: " << sizeof(Point) << " bytes" << std::endl;

int numbers[] = {1, 2, 3, 4, 5};
std::cout << "Size of numbers array: " << sizeof(numbers) << " bytes" << std::endl;

需要注意的是,sizeof 运算符返回的是对象或类型所占用的内存大小,并不考虑对象内部的对齐或填充。此外,对于动态分配的内存(如通过 new 运算符分配的内存),sizeof 运算符返回指针的大小,而不是指向对象的大小。

44. static

static(静态的)静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为 0,使用时可改变其值。静态变量或静态函数,只有本文件内的代码才可访问它,它的名字(变量名或函数名)在其它文件中不可见。因此也称为"文件作用域"。在 C++ 类的成员变量被声明为 static(称为静态成员变量),意味着它被该类的所有实例所共享,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其它所有实例所见;而类的静态成员函数也只能访问静态成员(变量或函数)。类的静态成员变量必须在声明它的文件范围内进行初始化才能使用,private 类型的也不例外。

static 关键字在 C++ 中用于声明静态成员或静态局部变量,具有不同的用法和语义。静态成员共享于类的所有对象,静态成员函数可以直接通过类名调用,而静态局部变量在程序的整个生命周期内只初始化一次。

三种用法介绍及代码示例:

① 声明静态成员变量:

在类中,static 关键字可以用于声明静态成员变量,这些变量被类的所有对象共享,而不是每个对象拥有一份独立的副本。

// 1. static用于声明静态成员变量
class MyClass {
public:
    static int count;
};
int MyClass::count = 0;  // 静态成员变量的定义和初始化

int main() {
    MyClass obj1;
    MyClass obj2;

    obj1.count = 5;
    std::cout << obj2.count << std::endl;  // 输出 5,count 是静态成员变量,被所有对象共享
    return 0;
}

在上述示例中,MyClass 类中的 count 是一个静态成员变量。通过使用 static 关键字,该变量被类的所有对象共享。我们可以直接通过对象或类名访问静态成员变量。

② 声明静态成员函数

在类中,static 关键字还可以用于声明静态成员函数,这些函数不依赖于任何对象,可以直接通过类名调用。

class MyClass {
public:
    static void printMessage() {
        std::cout << "Hello, world!" << std::endl;
    }
};

int main() {
    MyClass::printMessage();  // 直接通过类名调用静态成员函数
    return 0;
}

在上述示例中,MyClass 类中的 printMessage() 是一个静态成员函数。我们可以直接通过类名调用该函数,而无需创建类的对象。

③ 声明静态局部变量

在函数内部,static关键字可以用于声明静态局部变量,这些变量在程序的整个生命周期只初始化一次,并且在函数调用之间保持其值。

void increment() {
    static int counter = 0;  // 静态局部变量
    counter++;
    std::cout << "Counter: " << counter << std::endl;
}

int main() {
    increment();  // 输出 Counter: 1,第一次调用时初始化静态局部变量
    increment();  // 输出 Counter: 2,再次调用不会在初始化,保持其值
    increment();  // 输出 Counter: 3
    return 0;
}

在上述示例中,increment() 函数中的 counter 是一个静态局部变量。每次调用 increment() 函数时,counter 的值会递增并打印出来,但它的生命周期会持续到程序结束,而不是每次函数调用都会重新初始化。

静态局部变量在多线程环境下需要注意线程安全性。如果多个线程同时访问同一个静态局部变量,并且对其进行写操作,可能会导致竞争条件和数据不一致的问题。为了确保线程安全性,可以使用互斥锁(std::mutex)或其他线程同步机制来保护静态局部变量的访问。

#include <iostream>
#include <mutex>
void increment() {
	static int counter = 0; // 静态局部变量
	static std::mutex mutex; // 互斥锁
	std::lock_gaurd<std::mutex> lock(mutex); // 使用互斥锁保护访问
	counter++;
	std::cout << "Counter: " << counter << std::endl;
}
int main() {
	increment(); // 输出 COunter: 1
	increment(); // 输出 COunter: 2
	increment(); // 输出 COunter: 3
	return 0;
}	

在上述示例中,我们使用 std::mutex 来创建一个互斥锁 mutex,并在 increment() 函数中使用 std::lock_guard 对互斥锁进行加锁和解锁操作,以确保多个线程对静态局部变量 counter 的访问是互斥的,从而保证线程安全性。

45. static_cast

static_cast 是 C++ 中的一个类型转换操作符,用于进行静态类型转换。它可以用于类型之间的显式转换,但在进行转换时需要考虑类型的兼容性和安全性。

static_cast用法:

static_cast < type-id > ( expression ) 

该运算符把 expression 转换为 type-id 类型,但没有运行时类型检查来保证转换的安全性。

它主要有如下几种用法:

// 关键字static_cast的使用示例

// 1. 基本类型之间的转换
int num = 10;
double d = static_cast<double>(num); // num 的值转换为 double 类型,并将结果赋给变量 d

// 2. 类指针之间的转换
class Base { /* ...*/ }
class Derived : public Base { /* ...*/ };
Derived derived;
Base* basePtr = static_cast<Base*>(&derived); // 将派生类指针转换为基类指针。
// 这种转换通常用于处理多态对象的指针,以便在基类指针上调用基类的成员函数。

// 3. 类引用之间的转换
void process(Base& obj) {
	Derived& derivedRef = static_cast<Derived&>(obj); // 在函数内部将接受到的基类引用转换为派生类引用
}

用法归纳:
① 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
② 用于基本数据类型之间的转换,如把 int 转换成 char,把 int 转换成 enum。这种转换的安全性也要开发人员来保证。
③ 把空指针转换成目标类型的空指针。

// 使用 static_cast 将空指针 nullptr 转换为 int* 类型和 double* 类型的空指针
int* intPtr = static_cast<int*>(nullptr);
double* doublePtr = static_cast<double*>(nullptr);

④ 把任何类型的表达式转换成void类。

// 语法
static_cast<void>(expression);
// 示例
int num = 42;
double pi = 3.14;
static_cast<void>(num);
static_cast<void>(pi);

注意 static_cast 不能转换掉 expression 的 const、volitale、或者 __unaligned 属性。

46. struct

struct(结构)类型,类似于 class 关键字,与 C 语言兼容(class 关键字是不与 C 语言兼容的),可以实现面向对象程序设计。

struct 的主要特点是其默认的成员可见性是公共的(public),而 class 的默认成员可见性是私有的(private)。

#include <iostream>
// 定义一个结构体
struct Person {
	std::string name;
	int age;
	double height;
};
int main() {
	// 创建一个 Person 结构体对象
	Person p;
	p.name ="Alice";
	p.age = 25;
	p.height = 1.65;
	// 访问结构体成员
	std::cout << "Name: " << p.name << std::endl;
    std::cout << "Age: " << p.age << std::endl;
    std::cout << "Height: " << p.height << std::endl;
    return 0;
}

在上述代码中,我们使用 struct 关键字定义了一个名为 Person 的结构体,它包含了三个成员变量:name、age 和 height。然后,在 main 函数中,我们创建了一个 Person 结构体对象 p,并对其成员进行赋值和访问。

47. switch

switch(转换)类似于 if-else-if 语句,是一种多分枝语句。它提供了一种简洁的书写,并且能够生成效率更好的代码。但是,switch 后面的判断只能是int(char也可以,但char本质上也是一种int类型)。switch 语句最后的 default 分支是可选的。示例代码见关键字‘5.case’。

48. template

template(模板),C++ 中泛型机制的实现。通过使用模板,可以编写通用的代码,以处理不同类型的数据,从而实现代码的复用和灵活性。

模板通过参数化类型或值来定义通用的算法、数据结构或函数。在编写模板时,可以使用占位符类型(例如 T)或值(例如 N)来表示要在实例化时指定的具体类型或值。

// 关键字template的代码示例
// 展示如何使用模板创建一个通用的函数来计算两个数的和:
# include <iostream>
// 定义一个模板函数
template <typename T>
T add(T a, T b) {
	return a + b;
}
int main() {
	//  调用模板函数并打印结果
	std::cout << "Sum of integers:" << add(5, 7) << std::endl;
	std::cout << "Sum of doubles: " << add(3.14, 2.71) << std::endl;
	return 0;
}

在上述代码中,我们使用 template 定义了一个模板函数 add,它接受两个参数 a 和 b,类型为模板参数 T。函数的返回类型也是 T。通过这样的定义,我们可以在函数调用时传递不同类型的参数,并得到相应类型的结果。

在 main 函数中,我们通过使用 add 函数来计算整数和浮点数的和。在调用 add 函数时,编译器会根据实参的类型自动推断模板参数 T 的具体类型,并生成相应的函数实例。

使用模板可以实现通用的算法、数据结构和函数,提高代码的重用性和灵活性。可以根据实际需求,定义不同类型的模板,满足不同场景的编程需求。

49. this

this 返回调用者本身的指针。它在类的成员函数中被隐式地传递,并且可以用于访问当前对象的成员变量和成员函数。

this 指针提供了一个方式,让类的成员函数可以访问到调用该函数的对象的成员。它指向函数所属的对象本身,允许在函数内部引用对象的成员。

#include <iostream>
class MyClass {
private:
	int value;
public:
	void setValue(int val) {
		this->value = val;
	}
	int getValue() {
		return this->value;
	}
};
int main() {
	MyClass obj;
	obj.setValue(42);
	std::cout << "Value:" << obj.getValue() <<std::ensl;
	return 0;
}

在上述代码中,我们定义了一个名为 MyClass 的类,它包含一个私有成员变量 value。类中的 setValue 函数使用 this 指针来设置当前对象的成员变量值,而 getValue 函数使用 this 指针来获取当前对象的成员变量值。

在 main 函数中,我们创建了一个 MyClass 对象 obj,并通过调用 setValue 函数设置了成员变量的值为 42。然后,我们调用 getValue 函数获取成员变量的值,并将其打印输出。

通过使用 this 指针,类的成员函数可以访问当前对象的成员,避免命名冲突和歧义。它使得代码更清晰、易读,并且能够正确引用当前对象的成员。

50. throw

throw(抛出)用于实现 C++ 的异常处理机制,可以通过 throw 关键字"抛出"一个异常。这个异常对象可以是任何类型,但通常是派生自 std::exception 类或其子类的类型。抛出异常后,程序的控制权将传递给能够处理该异常的异常处理程序。

// 关键字throw的示例代码
// 演示了如何使用 throw 抛出异常和如何捕获并处理异常:
#include <iostream>
double divide(double numerator, double demoninator) {
	if (denominator == 0.0) {
		throw std::runtime_error("Division by zero is not allowed.");
	}
	return numerator / denominator;
}
int main() {
	try {
		double result = divide(10.0, 0.0);
		std::cout << "Result: " << result << std::endl;
	} catch (const std::expection& e) {
		std::cout << "Exception caught: " << e.what() << std::endl;
	}
	return 0;
}

在上述代码中,我们定义了一个 divide 函数,用于计算两个数的除法。如果分母为零,则抛出一个 std::runtime_error 类型的异常,并提供错误信息。在 main 函数中,我们通过调用 divide 函数来进行除法计算。由于分母为零,抛出了异常。在 catch 块中,我们捕获并处理了异常,并输出异常的错误信息。

使用 throw 关键字可以将异常抛出到当前执行上下文的调用栈中,直到找到能够处理该异常的异常处理程序。如果没有找到适当的异常处理程序,程序将终止并显示未处理的异常信息。

通过使用 throw 和异常处理机制,可以更好地处理程序中的错误和异常情况,提高程序的健壮性和可靠性。

51. true

true(真的),C++ 的基本数据结构 bool 类型的真值。等同于 int 的非 0 值。示例略。

52. try

try(尝试)用于实现 C++ 的异常处理机制。可以在 try 中调用可能抛出异常的函数,然后在 try 后面的 catch 中捕获并进行处理。

// try 和 catch 的基本用法示例:
try {
    // 可能引发异常的代码
    // ...
} catch (ExceptionType1& e1) {
    // 处理 ExceptionType1 类型的异常
    // ...
} catch (ExceptionType2& e2) {
    // 处理 ExceptionType2 类型的异常
    // ...
} catch (...) {
    // 处理其他未被上述 catch 块捕获的异常
    // ...
}

在 try 块中,包含了可能引发异常的代码。当某个异常被抛出时,会被 catch 块中匹配的异常处理器捕获,并执行相应的代码块。异常处理器的顺序与 catch 块的顺序相对应,第一个匹配的 catch 块将处理异常,而后续的 catch 块将被忽略。

异常处理器的参数是异常对象的引用,该对象可以用于访问有关异常的信息。如果某个 catch 块中的异常类型与实际抛出的异常类型匹配,该 catch 块将被执行,否则将继续查找匹配的 catch 块。

如果没有适用的 catch 块可以处理抛出的异常,异常将传播到调用栈的上一层,直到找到匹配的 catch 块或程序终止。

53. typedef

typedef(类型定义,type define),用于为现有的类型创建一个新的名称(别名)。通过 typedef,可以为复杂的类型或较长的类型名字创建一个更简洁、易于理解的别名,以提高代码的可读性和可维护性。

typedef 的语法格式为:

typedef existing_type new_type;

其中,existing_type 是已有的类型,可以是内置类型(如 int、float 等),也可以是自定义的类型(如结构体、类、指针等);new_type 是为现有类型创建的新的别名。

// 关键字typedef 的使用代码示例
typedef int Number;  // 创建 int 类型的别名 Number

typedef struct {
	int x;
	int y;
} Point; // 创建结构体类型的别名 Point

typedef int* IntPointer; // 创建指向 int 类型的指针的别名 IntPoninter

typedef void (*FuncPtr)(); // 创建函数指针类型的别名FuncPtr

int main() {
	Number n = 42;
	Point p = {10, 20};
	IntPointer ptr = &n;
	// 使用新的类型别名
	std::cout << "Number: " << n << std::endl;
	std::cout << "Point: (" << p.x << "," << p.y << ")" << std::endl;
	std::cout << "IntPointer:" << *ptr << std::endl;
	return 0;
}

在上述示例中,我们使用 typedef 分别创建了 Number、Point、IntPointer 和 FuncPtr 这些类型的别名。然后,我们声明了相应的变量并使用这些别名进行操作。通过使用这些别名,我们可以提高代码的可读性,并且在需要修改类型时,只需要修改一处即可。

注意,C++11 引入了更灵活和强大的类型别名机制 using,推荐在新代码中使用 using 来定义类型别名。例如,上述示例中的 typedef 可以使用 using 改写如下:

using Number = int;
using Point = struct {
	int x;
	int y;
};
using IntPoingter = int*;
using FuncPtr = void (*)();

使用 using 定义的类型别名与 typedef 完全等价,并且在语法上更加清晰和直观。

54. typeid

typeid 是一个运算符,用于获取表达式的类型信息。它返回一个 std::type_info 对象,该对象包含有关表达式的类型的信息。

// typeid 运算符的语法如下:
// typeid(expression)

// 以下是一个示例代码,演示了如何使用 typeid 运算符:
#include <iostream>
#include <typeinfo>
int main() {
    int num = 42;
    // 使用 typeid 获取变量 num 的类型信息
    const std::type_info& type = typeid(num);
    // 使用 type.name() 获取类型的名称
    std::cout << "Type of num: " << type.name() << std::endl;
    return 0;
}

在上述示例中,我们声明了一个 int 类型的变量 num。通过使用 typeid(num),我们获取到了 num 的类型信息,并将其存储在 type 变量中。然后,使用 type.name() 可以获取类型的名称,并将其输出到标准输出流。

需要注意的是,type.name() 返回的类型名称可能是由编译器定义的特定字符串,具体格式和内容可能因编译器而异。

55. typename

typename(类型名字)关键字,用于指示在模板中使用的标识符是一个类型而不是变量或函数。在模板中,当引用模板参数时,编译器无法确定该标识符是一个类型还是其他实体,因为模板参数可以是类型、变量或函数等。在这种情况下,我们需要使用 typename 关键字来明确告诉编译器该标识符是一个类型。

// 关键字typename的使用代码示例
#include <iostream>
template <typename T>
void printSize() {
	// 使用 typename 关键字告诉编译器 MyType 是一个类型
	typename T::MyType myVariable;
	std::cout << "Size of myVariable:" << sizeof(myVariable)
}
struct MyStruct {
	using MyType = int;
};
int main() {
	printSize<Mystruct>();
	return 0;
}

在上述示例中,我们定义了一个模板函数 printSize,接受一个模板参数 T。在函数内部,我们使用 typename 关键字来指示 T::MyType 是一个类型。然后,我们声明了一个变量 myVariable,其类型为 T::MyType。最后,我们输出 myVariable 的大小。

需要注意的是,在模板的非依赖名称中使用 typename 是必需的。而在依赖名称中(例如模板参数或嵌套从属类型),编译器通常可以推断出其为类型,因此不需要使用 typename。

56. union

union(联合),类似于 enum。不同的是 enum 实质上是 int 类型的,而 union 可以用于所有类型,并且其占用空间是随着实际类型大小变化的。

// union的语法如下: 
union UnionName {
	member1;
	menmber2;
	// ...
}

在一个 union 中,可以定义多个成员,每个成员可以是不同的类型。所有成员共享同一块内存,但只能访问最后一次存储的成员。

// 以下是一个示例代码,演示了 union 的使用:
#include <iostream>
union MyUnion {
	int intValue;
	float flaotValue;
	char charValue;
};
int main() {
	MyUnion u;
	u.intValue = 42;
	std::cout << "Value: "<< u.intValue << std::endl;
	u.floatValue = 3.14f;
	std::cout << "Value: " << u.floatValue << std::endl;
    u.charValue = 'A';
    std::cout << "Value: " << u.charValue << std::endl;
    std::cout << "Size of union: " << sizeof(u) << " bytes" << std::endl;
    return 0;
}

在上述示例中,我们定义了一个 union,名为 MyUnion。它包含了三个成员变量:intValue、floatValue 和 charValue,分别表示整数、浮点数和字符类型的值。我们创建了一个 MyUnion 类型的变量 u,并按顺序对其进行赋值。注意,每次赋值都会覆盖之前存储的值。最后,我们输出了变量的值以及 union 的大小。

需要注意的是,union 的使用需要谨慎,因为它具有一些潜在的问题。由于所有成员共享同一块内存,如果在访问时使用了错误的类型,可能会导致数据的解释错误或未定义行为。因此,在使用 union 时应谨慎,并确保正确地管理成员的访问和使用。

57. unsigned

unsigned(无符号),用于声明无符号整数类型,和 signed 相反。unsigned 可以与不同的整数类型一起使用,例如 unsigned int、unsigned short、unsigned long 等。这些类型的取值范围始终从零开始,直到其最大值。它们不包括负数,并且可以表示更大的正数范围。

unsigned int positiveNum = 20;

当与有符号整数类型进行混合运算时,无符号整数类型会自动进行符号扩展。

58. using

using用于创建别名和引入命名空间。using 可以用于创建类型别名,简化复杂的类型名称或引入自定义类型名称。using 也可以用于引入命名空间中的成员,使其在当前作用域内可直接访问,而无需使用限定符。

// 关键字using的使用代码示例
// 1. 别名声明:
using MyInt = int; // MyInt 现在是 int 的别名,可以用于声明整数变量
using StudentID = std::string; // StudentID 是 std::string 的别名,可以用于声明学生的学号。
MyInt num = 10;
StudentID id = "20210001";

//2. 命名空间引入
#include <iostream>
using namespace std;
int main() {
    cout << "Hello, world!" << endl;
    return 0;
}

在上述示例中,我们使用 using namespace std; 引入了 std 命名空间,使得在 main 函数内可以直接使用 cout 和 endl,而无需写成 std::cout 和 std::endl。

需要注意的是,在引入命名空间时要谨慎使用,尤其是在头文件中。使用 using namespace 可能导致命名冲突或引入不必要的符号,最好在有限的作用域内使用,或者使用具体的命名空间成员来避免冲突。

59. virtual

virtual(虚的),用于声明虚函数或实现多态性。通过在基类中的函数声明前添加 virtual 关键字,可以将该函数声明为虚函数。虚函数用于实现运行时多态性,即在派生类中可以通过覆盖(重写)基类的虚函数来实现不同的行为。

// 关键字virtual的一个使用代码示例
class Animal {
public:
    virtual void makeSound() {
        std::cout << "Animal makes sound." << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override { //虚函数覆盖时用override显性表示
        std::cout << "Dog barks." << std::endl;
    }
};

int main() {
    Animal* animal = new Dog();
    animal->makeSound(); // 调用的是 Dog 类中重写的 makeSound() 函数
    delete animal;
    return 0;
}

在上述示例中,Animal 类中的 makeSound() 函数被声明为虚函数。在派生类 Dog 中,我们重写了基类的虚函数,并实现了不同的行为。通过在 main() 函数中使用基类指针指向派生类对象,然后调用虚函数 makeSound(),可以在运行时根据实际对象的类型来调用适当的函数。

在派生类中重写基类的虚函数时,可以使用 override 关键字显式标识,以提高代码的可读性和清晰性。override 关键字告诉编译器,派生类中的函数是对基类虚函数的重写。

60. void

void(空的),可以作为函数返回值,表明不返回任何数据;可以作为参数,表明没有参数传入(C++中不是必须的);可以作为指针使用。

// 关键字void的使用代码示例
// 1. 函数返回类型:在函数声明或定义中,void 可用作函数的返回类型,表示函数不返回任何值。
void printMessage() {
    std::cout << "Hello, world!" << std::endl;
}

//2. 函数参数类型:void 可以用作函数的参数类型,表示函数不接受任何参数。
void process() {
    // 执行一些操作
}

//3. 指针类型:void* 是一种特殊的指针类型,表示指向未知类型的指针。它可以用于处理不确定类型的数据,但需要进行类型转换才能正确使用。
void main() {
	void* ptr = nullptr;
	int value = 42;
	ptr = &value; // 将 int 类型的指针赋值给 void* 类型的指针
	int* intValue = static_cast<int*>(ptr); // 将 void* 类型的指针转换为 int* 类型的指针
	return;
}	

61. volatile

volatile(不稳定的)用于声明变量为"易变"的,即告诉编译器该变量的值可能在程序的执行过程中被意外地改变,因此编译器在优化和访问该变量时需要特别注意。

使用 volatile 关键字修饰的变量,告诉编译器不要对该变量的读取和写入进行优化,以确保每次访问都直接从内存中读取或写入变量的值,而不使用缓存或寄存器。这对于一些特殊的情况非常重要,例如:

  1. 并发程序:当多个线程或进程同时访问同一个变量时,如果没有使用 volatile,编译器可能会对变量进行优化,导致不正确的结果或行为。

  2. 外部硬件访问:当程序需要与外部设备进行交互,例如读取传感器数据或控制硬件状态时,使用 volatile 可以确保读取和写入操作的顺序和精确性.

// 关键字volatile的一个使用代码示例
#include <iostream>
int main() {
	volatile int value = 0;
	while (value < 10) {
		std::cout << "Value: " << value << std::endl;
		value++;
	}
	return 0;
}

在上述示例中,我们声明了一个 volatile 整数变量 value,并使用它来控制一个循环。每次循环迭代,我们打印出 value 的值,并将其递增。由于 value 被声明为 volatile,编译器不会对其进行优化,确保每次读取和写入都是直接访问内存。

需要注意的是,volatile 关键字只表示该变量是易变的,而不提供任何线程安全性或原子性保证。在并发程序中,除了使用 volatile,还需要使用其他机制来确保线程安全性,例如使用互斥锁或原子操作。

62. wchar_t

wchar_t 一种数据类型,用于表示宽字符(wide character)。它是一种用于存储宽字符编码的整数类型,在不同的实现中可能具有不同的大小。

在大多数平台上,wchar_t 的大小通常为2个字节或4个字节,用于存储宽字符的 Unicode 编码。它可以表示更广范围的字符,包括非 ASCII 字符和特殊字符。

wchar_t 类型通常用于处理多语言和国际化的应用程序,其中需要处理各种字符集和字符编码。它提供了一种在程序中处理宽字符的方式,以便与多语言环境和 Unicode 字符集进行交互。

// 关键字 wchar_t 的使用代码示例
#include <iostream>
int main() {
	wchar_t ch = L'宽'// 宽字符使用'L'前缀
	std::wcout << "宽字符:" << ch <<std::endl;
	std::wcout << "宽字符的大小: " << sizeof(ch) << "字节" << std::endl;
	return 0;
}

在上述示例中,我们声明了一个 wchar_t 类型的变量 ch,并将其初始化为宽字符 ‘宽’。使用 std::wcout 输出流和 L’宽’ 表示宽字符。我们还使用 sizeof 运算符获取 wchar_t 类型的大小。

需要注意的是,wchar_t 类型在 C++ 中的使用可能因编译器和操作系统的不同而有所差异。在某些平台上,可能使用其他宽字符类型,例如 char16_t 或 char32_t 来支持更广泛的 Unicode 字符集。

【参考资料】

  1. C++ 的关键字(保留字)完整介绍
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

" 孙 。菩萨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值