C++学习专栏【基础知识1】C++程序结构&命名空间&关键字&标识符&三字符序列

一、C++程序结构

让我们看一个简单的代码,它将打印Hello World一词。

#include 
using namespace std;
int main() {
   cout << "Hello World"; // prints Hello World
   return 0;
}

C++语言定义了几个头文件,其中包含对你的程序必要或有用的信息。对于这个程序,需要头文件

using namespace std;这一行告诉编译器使用std命名空间。命名空间是C++中相对较新的一个添加内容

int main() 是程序执行开始的主函数

cout << "Hello World"; 导致屏幕上显示消息"Hello World"

return 0; 终止 main() 函数并使其返回值为 0 给调用进程

二、C++命名空间是什么?

想象一下,你住在一座大城市,这个城市被划分成不同的区域:市中心、住宅区、商业区等等。每个区域都有独特的街道、建筑和规则。在这个场景中,每个区域就是一个命名空间,它们提供了独立的作用域,允许你在其中声明和使用标识符,而这些标识符的名字在不同的命名空间中可以重复使用,因为它们互相隔离。

普通命名空间定义

在C++中,我们可以使用关键字namespace来定义命名空间。比如:

// 定义名为math的命名空间
namespace math {
    const double PI = 3.14159;

    double areaOfCircle(double radius) {
        return PI * radius * radius;
    }
}

上面的代码定义了一个名为 math 的命名空间。它包含了一个常量 PI 和一个计算圆面积的函数 areaOfCircle

就像城市中的区域可以进一步划分为子区域一样,命名空间也可以嵌套定义。例如:

命名空间的嵌套

namespace university {
    namespace department {
        void displayInfo() {
            std::cout << "Welcome to Computer Science Department!" << std::endl;
        }
    }
}

 这里,我们有一个嵌套的命名空间结构。university 是外层命名空间,内部有 department 命名空间,其中包含了一个显示信息的函数。

命名空间的使用

使用命名空间可以通过两种主要的方式:

限定名:使用作用域解析运算符::来访问命名空间中的成员,例如:

std::cout << "Hello, World!";

university::department::displayInfo();

这里的 std:: 表示标准命名空间,cout 是其中的一个成员。

小知识:

C++标准库中的 std 命名空间是什么?为什么要使用它?

std 命名空间是 C++ 标准库的命名空间,包含了标准库中的大部分功能、类和对象。使用 std 命名空间可以避免与用户定义的标识符产生冲突,并让代码更具可移植性。要使用标准库的标识符(如 std::coutstd::vector),需要显式地指明其命名空间。

使用指令:通过 using 指令将整个命名空间的内容引入当前作用域,例如

using namespace math;

using namespace university::department;

这将使得 math 命名空间中的所有内容在当前作用域内可用,但要注意这种方法可能会引入命名冲突。

示例:使用普通命名空间

现在,让我们结合实际的例子来展示命名空间的使用:

#include 

// 定义名为math的命名空间
namespace math {
    const double PI = 3.14159;

    double areaOfCircle(double radius) {
        return PI * radius * radius;
    }
}

int main() {
    // 使用限定名调用命名空间中的函数
    std::cout << "Area of circle with radius 2: " << math::areaOfCircle(2.0) << std::endl;

    // 使用指令引入命名空间中的常量
    using namespace math;
    std::cout << "Value of PI: " << PI << std::endl;

    return 0;
}

这个示例中,我们展示了如何使用限定名来调用命名空间中的函数,以及如何使用 using namespace 指令将命名空间中的常量引入当前作用域。

示例:使用嵌套命名空间

#include 

namespace university {
    namespace department {
        void displayInfo() {
            std::cout << "Welcome to Computer Science Department!" << std::endl;
        }
    }
}

int main() {
    // 通过限定名调用嵌套命名空间中的函数
    university::department::displayInfo();

    // 使用指令引入嵌套命名空间
    using namespace university::department;
    displayInfo(); // 现在可以直接使用 displayInfo(),因为已经引入了 department 命名空间

    return 0;
}

在这个示例中,我们展示了使用限定名和使用指令两种方式来使用嵌套命名空间。通过这些方法,我们可以方便地访问嵌套命名空间中的成员,使得代码更具有结构性和可读性。

总的来说,命名空间是C++中一种强大的工具,帮助我们组织和管理代码,避免命名冲突,提高代码的可读性和可维护性。

 三、C++的关键字

下面的列表显示了 C++ 中的保留字。这些保留字不得用作常量、变量或任何其他标识符名称,加粗的为C语言的关键字

asm else new this
auto enum operator throw
bool explicit private true
break export protected try
case extern public typedef
catch false register typeid
char float reinterpret_cast typename
class for return union
const friend short unsigned
const_cast goto signed using
continue if sizeof virtual
default inline static void
delete int static_cast volatile
do long struct wchar_t
double mutable switch while
dynamic_cast namespace template

以下是 C++ 中关键字的解释:

  • Asm:用于声明需要传递给汇编器的代码块。
  • auto:用作存储类别说明符,在特定块中定义对象。
  • break:终止任何 switch 语句或循环。
  • case:在 switch 语句中使用,指定语句表达式的匹配项。
  • catch:指定异常发生时应采取的操作。
  • char:C++ 语言中的基本数据类型之一,定义字符对象。
  • class:用于声明封装特定类的数据成员、操作或成员函数的用户定义数据类型。
  • const:帮助定义在程序执行的整个生命周期中值不会改变的对象。
  • continue:将控制转移到循环的起始点。
  • default:处理 switch 语句中无法处理的表达式值。
  • delete:内存释放运算符。
  • do:指示 do-while 语句的起点,在其中子语句将重复执行,直到表达式的值为逻辑假。
  • double:用于定义浮点数的基本数据类型。
  • else:特定于 if-else 语句的使用。
  • enum:声明用户定义的枚举数据类型。
  • extern:指定为外部的标识符与块具有外部链接。
  • float:用于定义浮点数的基本数据类型。
  • for:指示开始一个语句以实现重复控制。
  • friend:一个类或操作,其实现可以访问另一个类的私有数据成员。
  • long:数据类型修饰符,定义 32 位整数或扩展双精度数。
  • new:内存分配运算符。
  • operator:使用新声明重载 C++ 运算符。
  • private:声明在类外部不可见的类成员。
  • protected:声明对派生类除外的私有类成员。
  • public:声明在类外部可见的类成员。
  • register:存储类别说明符,是 auto 说明符,但也指示编译器将频繁使用的对象保留在寄存器中。
  • goto:帮助将控制权转移到指定的标签。
  • if:指示开始 if 语句以实现选择性控制。
  • inline:函数说明符,指示编译器优先选择内联替换函数体,而不是通常的函数调用实现。
  • int:定义整数对象的基本数据类型。
  • return:将对象返回给函数的调用者。
  • short:定义 16 位整数的数据类型修饰符。
  • signed:数据类型修饰符,指示对象的符号存储在高阶位。
  • sizeof:以字节为单位返回对象的大小。
  • static:静态定义的对象生存期存在于程序执行的整个生命周期。
  • struct:声明封装数据和成员函数的新类型。
  • switch:用于 switch 语句。
  • template:参数化或通用类型。
  • this:指向类的对象或实例的类指针。
  • throw:生成异常。
  • try:指示异常处理程序块的开始。
  • typedef:另一个整数或用户定义类型的同义词。
  • union:类似于结构体 struct,可以容纳不同类型的数据,但联合体只能同时容纳一个成员。
  • unsigned:数据类型修饰符,指示高阶位将用于一个对象。
  • virtual:函数说明符,声明一个类的成员函数将由派生类重新定义。
  • void:标识缺乏类型或函数参数列表的关键字。
  • volatile:这个特定关键字定义了一个对象,其值可能以编译器无法检测到的方式变化。
  • while:帮助启动 while 语句并结束 do...while 循环。

在编译器优化中,inline 关键字用于向编译器建议将函数内容直接插入函数调用的地方,而不是进行常规的函数调用。这样的建议通常用于短小的函数,以提高程序的执行效率。

1、inline 关键字

1.1 inline 关键字的作用:
  1. 减少函数调用开销: 普通函数的调用涉及堆栈操作、参数传递、指令跳转等开销,而使用 inline 关键字可以避免这些开销,直接将函数体内容嵌入到调用点处。

  2. 减少函数开销: 函数调用会产生一定的开销,如保存寄存器状态等。将函数内联可以减少这些开销,尤其在多次调用的场景中。

  3. 优化循环和小函数: inline 更适合用于简单的、执行频率高的函数或者循环体,因为在这些情况下,函数调用的开销相对更大。

1.2 影响程序性能的因素:
  1. 代码膨胀: inline 函数的函数体直接嵌入调用点,可能导致代码的膨胀,增加可执行代码的大小,对缓存和内存占用可能产生影响。

  2. 适用范围有限: 编译器可能会忽略 inline 关键字的建议,特别是对于复杂的函数、递归函数或函数体过大的情况。因此,即使使用了 inline,也不一定会被编译器完全内联。

  3. 编译器依赖: 编译器对 inline 关键字的处理方式可能因编译器而异,不同编译器可能会有不同的优化方式,对程序性能的影响也会有所不同。

  4. 适用于简短函数: 对于函数体较大、复杂的情况,inline 的效果可能不如预期,甚至可能因代码膨胀而降低性能。

#include 

// 定义一个简单的加法函数
inline int add(int a, int b) {
    return a + b;
}

int main() {
    int x = 5, y = 10;
    int result = add(x, y); // 调用 add() 函数

    std::cout << "Result: " << result << std::endl;
    return 0;
}

总的来说,inline 关键字能够在一定程度上提高程序性能,但使用时需慎重考虑函数的大小、调用频率以及编译器的优化能力,避免不必要的代码膨胀,从而达到更好的性能优化效果。

四、C++ 标识符

C++ 标识符是用于标识变量、函数、类、模块或任何其他用户定义项的名称。标识符以字母 A 到 Z 或 a 到 z 或下划线 (_) 开头,后跟零个或多个字母、下划线和数字(0 到 9)。

C++ 不允许在标识符中使用标点符号,C++ 是一种区分大小写的编程语言。

五、三字符序列(Trigraphs)

三字符序列是一种用于代表单个字符的替代表示方法,通常由三个字符组成,并且序列始终以两个问号开始。

三字符序列可以在出现的任何地方进行扩展,包括字符串字面值和字符字面值、注释以及预处理指令。

以下是最常用的三字符序列及其替换方式:

三字符序列 替换
??= #
??/ \
??' ^
??( [
??) ]
??! |
??< {
??> }
??- ~

并非所有编译器都支持三字符序列,而且由于它们容易造成混淆,不建议使用。

六、思考总结

C++ 中的 const 和 volatile 关键字有什么作用?它们在嵌入式系统中有什么应用?

  • const 关键字:用于定义常量,标识变量的数值不可修改。在嵌入式系统中,const 关键字常用于声明设备寄存器地址、常量表和程序代码的位置等。

  • volatile 关键字:用于声明易变的变量,告诉编译器该变量的值可能在程序控制之外发生改变,不应该被优化掉。在嵌入式系统中,volatile 常用于多线程编程、并行处理、硬件寄存器和中断服务程序中,确保编译器不会对这些值进行优化或缓存。

请解释关键字 auto 和 register 在 C++ 中的用途及其区别。

  • auto 关键字:在 C++11 中,auto 关键字用于自动推断变量的类型。它允许编译器根据变量的初始化表达式来推断变量的数据类型。

  • register 关键字:register 告诉编译器将变量存储在寄存器中以便快速访问。然而,现代编译器已经足够智能,在大多数情况下能够自行决定将变量存储在寄存器还是内存中。因此,register 关键字在现代编译器中往往不再被频繁使用。

typedef 关键字在 C++ 中有何作用?能否给出一个使用 typedef 的实际例子?

  • typedef 关键字:用于为现有的类型创建别名。它可以帮助简化复杂的类型名称,提高代码可读性,并减少代码中的重复。
// 实际例子:
typedef int IntArray[5]; // 创建一个名为 IntArray 的数组类型别名

int main() {
    IntArray arr = {1, 2, 3, 4, 5}; // 使用 IntArray 类型别名创建数组
    // ...
    return 0;
}

在上面的例子中,IntArray 被定义为一个具有5个整数元素的数组类型别名,使得声明数组变得更简洁。

C++ 中的 static 关键字有什么作用?

  • static 关键字在不同的上下文中有不同的作用。在类内部,它用于声明静态成员变量和静态成员函数。在函数内部,它表示局部变量的生命周期在程序的整个执行过程中都存在。

你可能感兴趣的:(C++学习专栏,c++,学习,算法)