C++ 入门:C++ 语言基础知识


C++ 入门:C++ 语言基础知识详解

C++ 是一种功能强大、应用广泛的编程语言,它既保留了C语言高效、接近底层的特性,又融入了面向对象编程(OOP)的思想,使得开发大型、复杂的应用程序变得更加容易。本文将带你深入了解C++的基础知识,为你的编程之旅打下坚实的基础。

1. C++ 简介与历史

C++ 的历史可以追溯到20世纪70年代末,由Bjarne Stroustrup在贝尔实验室开发。最初,它被称为“带类的C”(C with Classes),是对C语言的扩展,增加了面向对象的特性,如类、继承、多态等。1983年,它被正式命名为C++。

C++ 的发展经历了多个版本的迭代,重要的标准包括:

  • C++98:第一个C++标准,奠定了C++的基础。
  • C++03:对C++98的修订,修复了一些问题。
  • C++11:一个重要的里程碑,引入了许多现代特性,如自动类型推导、lambda表达式、智能指针等,极大地提升了开发效率。
  • C++14:对C++11的补充和完善。
  • C++17:引入了更多实用特性,如结构化绑定、std::optionalstd::variant等。
  • C++20:最新的标准,带来了概念(Concepts)、协程(Coroutines)、模块(Modules)等重大改进。

C++ 广泛应用于各种领域,包括:

  • 操作系统:如Windows、Linux、macOS的部分组件。
  • 游戏开发:许多大型游戏引擎和游戏都是用C++开发的。
  • 数据库:如MySQL、MongoDB等。
  • 浏览器:如Chrome、Firefox的部分组件。
  • 嵌入式系统:由于其高效性和对硬件的控制能力,C++在嵌入式领域也很受欢迎。
  • 高性能计算:科学计算、金融建模等领域。

2. 开发环境搭建

要开始编写C++程序,你需要一个合适的开发环境。这通常包括:

  • 编译器:将C++源代码转换为机器可执行代码的工具。常见的编译器有:
    • GCC (GNU Compiler Collection):开源、跨平台,广泛用于Linux和macOS。
    • Clang:基于LLVM,开源、跨平台,以其出色的错误诊断而闻名。
    • Microsoft Visual C++ (MSVC):Windows平台上的官方编译器,集成在Visual Studio中。
  • 编辑器/IDE:用于编写和编辑代码的工具。你可以选择:
    • Visual Studio:功能强大的集成开发环境(IDE),提供代码编辑、编译、调试、版本控制等一站式服务。
    • Visual Studio Code (VS Code):轻量级、可扩展的代码编辑器,通过安装插件可以支持C++开发。
    • CLion:JetBrains出品的跨平台C++ IDE,提供智能代码补全、重构、调试等功能。
    • Code::Blocks:开源、跨平台的C++ IDE,简单易用。
    • 文本编辑器 + 命令行:你可以使用任何文本编辑器(如Notepad++、Sublime Text、Vim等)编写代码,然后通过命令行调用编译器进行编译。
  • 调试器:用于查找和修复代码中的错误。常见的调试器有:
    • GDB:GCC的默认调试器,功能强大,但使用起来相对复杂。
    • LLDB:Clang/LLVM的默认调试器。
    • Visual Studio Debugger:集成在Visual Studio中。

安装步骤(以Windows和Visual Studio为例):

  1. 下载Visual Studio:访问Visual Studio官网,下载Community(社区版)即可,它是免费的。
  2. 安装Visual Studio:运行安装程序,选择“使用C++的桌面开发”工作负载,然后点击“安装”。
  3. 创建项目:打开Visual Studio,选择“创建新项目”,然后选择“空项目”或“控制台应用程序”模板。
  4. 编写代码:在项目中创建源文件(.cpp),编写你的C++代码。
  5. 编译和运行:点击“生成”菜单中的“生成解决方案”来编译代码,然后点击“调试”菜单中的“开始执行(不调试)”或“开始调试”来运行程序。

3. 第一个C++程序:Hello, World!

让我们从经典的“Hello, World!”程序开始:

```cpp

include

int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
```

代码解释:

  • #include <iostream>:这是一个预处理指令,告诉编译器包含iostream头文件。iostream提供了输入输出流对象,如std::cout(标准输出)和std::cin(标准输入)。
  • int main() { ... }:这是程序的主函数,程序的执行从这里开始。int表示函数的返回值类型是整数,main是函数名。
  • std::cout << "Hello, World!" << std::endl;:这行代码将字符串"Hello, World!"输出到控制台。
    • std::cout:标准输出流对象,用于向控制台输出数据。
    • <<:插入运算符,将后面的内容插入到输出流中。
    • "Hello, World!":字符串字面量,要输出的文本。
    • std::endl:插入一个换行符,并刷新输出缓冲区,确保内容立即显示。
  • return 0;main函数的返回值,表示程序的退出状态。通常,返回0表示程序成功执行,非0值表示出现错误。

编译和运行:

  1. 将代码保存为.cpp文件(如hello.cpp)。
  2. 打开命令行或终端。
  3. 使用编译器编译代码:
    • GCC/Clangg++ hello.cpp -o helloclang++ hello.cpp -o hello
    • MSVCcl hello.cpp
  4. 运行生成的可执行文件:
    • Linux/macOS./hello
    • Windowshello.exe

你应该能在控制台看到输出:Hello, World!

4. 基本语法

4.1. 注释

注释用于解释代码,不会被编译器执行。C++支持两种注释方式:

  • 单行注释:以//开头,直到行尾。

    cpp
    // 这是单行注释
    int x = 10; // 这也是单行注释

  • 多行注释:以/*开头,以*/结尾,可以跨越多行。

    cpp
    /*
    * 这是多行注释
    * 可以跨越多行
    */
    int y = 20;

4.2. 变量和数据类型

变量用于存储数据。在C++中,变量必须先声明后使用,声明时需要指定变量的类型。

基本数据类型:

  • 整型
    • int:整数,通常占用4个字节(32位)。
    • short:短整数,通常占用2个字节(16位)。
    • long:长整数,通常占用4个字节(32位)或8个字节(64位)。
    • long long:更长的整数,通常占用8个字节(64位)。
    • unsigned intunsigned shortunsigned longunsigned long long:无符号整数,只能表示非负数。
  • 浮点型
    • float:单精度浮点数,通常占用4个字节(32位)。
    • double:双精度浮点数,通常占用8个字节(64位)。
    • long double: 扩展精度浮点类型。通常占用12或16个字节
  • 字符型
    • char:字符,通常占用1个字节(8位),用于存储单个字符(如字母、数字、符号等)。
    • wchar_t:宽字符,用于存储Unicode字符。
  • 布尔型
    • bool:布尔值,只有两个值:true(真)和false(假)。

变量声明和初始化:

```cpp
int age; // 声明一个整型变量age
age = 25; // 给age赋值

double price = 99.99; // 声明并初始化一个双精度浮点型变量price

char grade = 'A'; // 声明并初始化一个字符型变量grade

bool is_valid = true; // 声明并初始化一个布尔型变量is_valid
```

变量命名规则:

  • 变量名可以包含字母、数字和下划线。
  • 变量名必须以字母或下划线开头。
  • 变量名不能是C++的关键字(如intdoubleiffor等)。
  • 变量名区分大小写(ageAge是不同的变量)。
  • 建议变量名要有意义, 使用描述性的词语, 增加程序可读性.

4.3. 运算符

C++提供了丰富的运算符,用于执行各种操作。

  • 算术运算符+(加)、-(减)、*(乘)、/(除)、%(取模)。
  • 关系运算符==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)。
  • 逻辑运算符&&(逻辑与)、||(逻辑或)、!(逻辑非)。
  • 赋值运算符=(赋值)、+=-=*=/=%=等。
  • 自增自减运算符++(自增)、--(自减)。
  • 位运算符&(按位与)、|(按位或)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移)。
  • 其他运算符sizeof(获取大小)、&(取地址)、*(解引用)、.(成员访问)、->(指针成员访问)、?:(三元条件运算符)等。

示例:

```cpp
int a = 10, b = 5;
int sum = a + b; // 加法
int diff = a - b; // 减法
int product = a * b; // 乘法
int quotient = a / b; // 除法
int remainder = a % b; // 取模

bool isEqual = (a == b); // 比较是否相等
bool isGreater = (a > b); // 比较是否大于

int x = 5;
x++; // x变为6
x--; // x变回5

int y = 10;
y += 5; // y变为15 (相当于 y = y + 5)
```

4.4. 表达式和语句

  • 表达式:由运算符和操作数组成的式子,可以计算出一个值。例如:a + bx * y - 5
  • 语句:以分号(;)结尾的代码行,表示一个完整的操作。例如:int sum = a + b;std::cout << "Hello";

4.5. 控制流

控制流语句用于控制程序的执行顺序。

  • 顺序结构:代码按照从上到下的顺序依次执行。
  • 选择结构:根据条件判断,选择执行不同的代码块。

    • if语句

      cpp
      if (condition) {
      // 如果condition为true,执行这里的代码
      } else if (another_condition) {
      // 如果another_condition为true,执行这里的代码
      } else {
      // 如果所有条件都不满足,执行这里的代码
      }

    • switch语句

      cpp
      switch (expression) {
      case value1:
      // 如果expression等于value1,执行这里的代码
      break;
      case value2:
      // 如果expression等于value2,执行这里的代码
      break;
      default:
      // 如果expression不等于任何case的值,执行这里的代码
      }

  • 循环结构:重复执行一段代码,直到满足特定条件。

    • while循环

      cpp
      while (condition) {
      // 只要condition为true,就重复执行这里的代码
      }

    • do-while循环

      cpp
      do {
      // 至少执行一次这里的代码,然后只要condition为true,就重复执行
      } while (condition);

    • for循环

      cpp
      for (initialization; condition; update) {
      // 先执行initialization,然后只要condition为true,就重复执行这里的代码,每次循环后执行update
      }

      * 基于范围的for循环 (C++11)
      cpp
      int numbers[] = {1,2,3,4,5};
      for (int num : numbers){
      std::cout << num << " ";
      } //输出 1 2 3 4 5

      * 跳转语句:
      * break: 跳出当前循环或switch语句
      * continue: 跳过当前循环的剩余部分, 直接开始下一次循环.
      * return: 从函数中返回.
      * goto: 无条件跳转到标签指定的位置 (不推荐使用)

示例:

```cpp
int score = 85;

if (score >= 90) {
std::cout << "优秀" << std::endl;
} else if (score >= 80) {
std::cout << "良好" << std::endl;
} else if (score >= 60) {
std::cout << "及格" << std::endl;
} else {
std::cout << "不及格" << std::endl;
}

int i = 1;
while (i <= 5) {
std::cout << i << " ";
i++;
} // 输出 1 2 3 4 5

for (int j = 0; j < 5; j++) {
std::cout << j << " ";
} // 输出 0 1 2 3 4
```

5. 函数

函数是一段封装好的、可重用的代码块,用于执行特定的任务。

函数定义:

cpp
return_type function_name(parameter_list) {
// 函数体
return value; // 如果函数有返回值
}

  • return_type:函数的返回值类型,可以是任何数据类型,如果函数没有返回值,则使用void
  • function_name:函数名,遵循变量命名规则。
  • parameter_list:函数的参数列表,可以包含零个或多个参数,每个参数由类型和名称组成,多个参数之间用逗号分隔。
  • 函数体:包含函数要执行的代码。
  • return value;:如果函数有返回值,使用return语句返回一个值。

函数调用:

cpp
function_name(argument_list);

  • argument_list:传递给函数的实际参数列表,参数个数和类型必须与函数定义中的参数列表匹配。

示例:

```cpp
// 定义一个函数,计算两个整数的和
int add(int a, int b) {
return a + b;
}

int main() {
int x = 10, y = 20;
int sum = add(x, y); // 调用add函数,并将返回值赋给sum
std::cout << "Sum: " << sum << std::endl; // 输出 Sum: 30
return 0;
}
```

函数重载:

C++允许定义多个同名函数,只要它们的参数列表不同(参数个数、类型或顺序不同)。这称为函数重载。

```cpp
int add(int a, int b) {
return a + b;
}

double add(double a, double b) {
return a + b;
}

int main() {
int sum1 = add(10, 20); // 调用int add(int, int)
double sum2 = add(10.5, 20.5); // 调用double add(double, double)
return 0;
}
```

6. 数组

数组是用于存储一系列相同类型元素的集合。

数组声明:

cpp
type array_name[array_size];

  • type:数组中元素的类型。
  • array_name:数组名。
  • array_size:数组的大小,必须是常量表达式。

数组初始化:

cpp
int numbers[5] = {1, 2, 3, 4, 5}; // 初始化一个包含5个整数的数组
int scores[] = {90, 85, 95}; // 编译器会自动推断数组大小为3
char grades[3] = {'A', 'B', 'C'}; // 初始化一个包含3个字符的数组

数组访问:

使用下标(索引)访问数组元素,下标从0开始,到array_size - 1结束。

cpp
int first = numbers[0]; // 获取第一个元素
numbers[1] = 10; // 修改第二个元素

多维数组:

C++支持多维数组,最常见的是二维数组。

```cpp
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};

int element = matrix[1][2]; // 获取第2行第3列的元素 (值为7)
```

7. 指针

指针是一种特殊的变量,它存储的是另一个变量的内存地址。

指针声明:

cpp
type *pointer_name;

* type: 指针所指向的变量的类型。
* pointer_name: 指针变量的名称。

取地址运算符(&):
用于获取变量的内存地址。

解引用运算符(*):
用于访问指针所指向的变量的值。

示例:

```cpp
int x = 10;
int *ptr = &x; // ptr指向x的内存地址

std::cout << "x的值: " << x << std::endl; //输出10
std::cout << "x的地址: " << &x << std::endl; //输出x的内存地址
std::cout << "ptr存储的地址: " << ptr << std::endl; //输出ptr存储的地址(和&x相同)
std::cout << "ptr指向的值: " << *ptr << std::endl; //输出ptr指向的值(和x相同,为10)

*ptr = 20; // 通过指针修改x的值
std::cout << "修改后x的值: " << x << std::endl; //输出20

``
**空指针:**
空指针是指不指向任何有效内存地址的指针。可以使用
nullptr(C++11推荐)或NULL`来表示空指针。

cpp
int *p = nullptr;

指针运算:
指针可以进行加减运算, 但意义与普通整数不同. 指针加1, 实际上是移动到下一个同类型元素的地址。
```cpp
int arr[5] = {1,2,3,4,5};
int *p = arr;

std::cout << p << std::endl; //输出 1
p++;
std::cout <<
p << std::endl; //输出 2

```

指针和数组:
数组名在大多数情况下会被解释为指向数组首元素的指针。
```cpp
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // ptr指向数组arr的第一个元素

std::cout << ptr[0] << std::endl; // 输出 1 (等价于 arr[0])
std::cout << (ptr + 1) << std::endl; // 输出 2 (等价于 arr[1])
**动态内存分配:**
使用`new`和`delete`运算符可以在运行时动态分配和释放内存。
cpp
int
p = new int; //分配一个int大小的内存空间
p = 10;
std::cout <<
p << std::endl;
delete p; //释放内存空间

// 动态分配数组
int *arr = new int[5];
for(int i=0; i<5; ++i){
arr[i] = i+1;
}

delete[] arr; //释放数组内存空间
```
指针的进阶应用:
* 指向指针的指针(二级指针)
* 函数指针
* 智能指针(C++11)

8. 字符串

在C++中,处理字符串有两种主要方式:

  • C风格字符串:字符数组,以空字符(\0)结尾。
  • std::string:C++标准库提供的字符串类,更安全、更方便。

8.1. C风格字符串

```cpp
char str1[] = "Hello"; // 编译器会自动添加空字符
char str2[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 手动添加空字符

std::cout << str1 << std::endl; // 输出 Hello
std::cout << str2 << std::endl; // 输出 Hello
```

常用C风格字符串函数(需要包含<cstring>头文件):

  • strlen(str):获取字符串长度(不包括空字符)。
  • strcpy(dest, src):将src字符串复制到dest
  • strcat(dest, src):将src字符串追加到dest末尾。
  • strcmp(str1, str2):比较两个字符串,相等返回0,str1大于str2返回正数,str1小于str2返回负数。

注意: C风格字符串操作容易出错,如缓冲区溢出等,需要小心处理。

8.2. std::string

```cpp

include

std::string str1 = "Hello";
std::string str2 = "World";

std::cout << str1 << " " << str2 << std::endl; // 输出 Hello World

// 常用std::string操作:
std::cout << str1.length() << std::endl; // 获取长度
std::cout << str1 + str2 << std::endl; // 字符串拼接
str1 += str2; // 追加字符串
std::cout << str1 << std::endl; // 输出 HelloWorld
std::cout << str1.substr(0, 5) << std::endl; // 获取子串 (输出 Hello)
std::cout << str1.find("World") << std::endl; // 查找子串 (返回位置)
std::cout << (str1 == str2) << std::endl; // 比较字符串
```

std::string类提供了丰富的成员函数,可以方便地进行字符串操作,并且比C风格字符串更安全。

9. 结构体(Structures)

结构体是一种自定义数据类型,可以将不同类型的数据组合在一起。

结构体定义:

cpp
struct Person {
std::string name;
int age;
double height;
};

结构体变量声明和初始化:

```cpp
Person p1;
p1.name = "Alice";
p1.age = 30;
p1.height = 1.75;

Person p2 = {"Bob", 25, 1.80};
```

结构体成员访问:

使用.运算符访问结构体成员。

cpp
std::cout << p1.name << std::endl; // 输出 Alice
std::cout << p2.age << std::endl; // 输出 25

结构体指针:

cpp
Person *ptr = &p1;
std::cout << ptr->name << std::endl; // 输出 Alice (使用->运算符访问成员)

10. 输入输出流

C++使用输入输出流(I/O streams)来处理输入和输出。

  • std::cin:标准输入流,用于从键盘读取输入。
  • std::cout:标准输出流,用于向控制台输出数据。
  • std::cerr:标准错误流,用于输出错误信息。
  • std::clog:标准日志流,用于输出日志信息。

使用>>(提取运算符)从输入流读取数据:

cpp
int age;
std::cout << "Enter your age: ";
std::cin >> age; // 从键盘读取一个整数,并存储到age变量中

使用<<(插入运算符)向输出流输出数据:

cpp
std::cout << "Your age is: " << age << std::endl;

格式化输出:

可以使用iomanip头文件中的操纵符来格式化输出。

```cpp

include

double pi = 3.141592653589793238;

std::cout << std::fixed << std::setprecision(2) << pi << std::endl; // 输出 3.14 (保留两位小数)
```

11. 文件输入输出

C++使用文件流来读写文件。

  • std::ifstream:输入文件流,用于从文件读取数据。
  • std::ofstream:输出文件流,用于向文件写入数据。
  • std::fstream:文件流,可以同时进行读写操作。

示例:

```cpp

include

include

include

int main() {
// 写入文件
std::ofstream outfile("example.txt");
if (outfile.is_open()) {
outfile << "Hello, File!" << std::endl;
outfile << "This is a test." << std::endl;
outfile.close(); // 关闭文件
} else {
std::cerr << "Unable to open file for writing." << std::endl;
}

// 读取文件
std::ifstream infile("example.txt");
std::string line;
if (infile.is_open()) {
    while (std::getline(infile, line)) { // 逐行读取
        std::cout << line << std::endl;
    }
    infile.close(); // 关闭文件
} else {
    std::cerr << "Unable to open file for reading." << std::endl;
}

return 0;

}
```

12. 命名空间(Namespaces)

命名空间用于避免命名冲突,可以将代码组织到不同的逻辑单元中。

命名空间定义:

```cpp
namespace MyNamespace {
int x = 10;

void myFunction() {
    std::cout << "Hello from MyNamespace" << std::endl;
}

}
```

命名空间使用:

  • 使用作用域解析运算符(::

    cpp
    std::cout << MyNamespace::x << std::endl; // 输出 10
    MyNamespace::myFunction(); // 输出 Hello from MyNamespace

  • 使用using声明

    cpp
    using MyNamespace::x;
    std::cout << x << std::endl; // 输出 10

  • 使用using指令

    cpp
    using namespace MyNamespace;
    std::cout << x << std::endl; // 输出 10
    myFunction(); // 输出 Hello from MyNamespace

注意: using指令可能会引入命名冲突,谨慎使用。

总结

本文详细介绍了C++语言的基础知识,包括数据类型、运算符、控制流、函数、数组、指针、字符串、结构体、输入输出流、文件输入输出和命名空间。掌握这些基础知识是学习C++的关键,希望本文能帮助你入门C++编程。

当然,C++ 是一门非常庞大和复杂的语言,本文只是介绍了最基础的部分。要深入学习C++,还需要学习更多高级特性,如类、对象、继承、多态、模板、STL(标准模板库)、异常处理等。 建议你通过阅读更多书籍、教程、参考资料,以及编写更多代码来不断提升你的C++编程技能。祝你学习顺利!

THE END