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::optional
、std::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为例):
- 下载Visual Studio:访问Visual Studio官网,下载Community(社区版)即可,它是免费的。
- 安装Visual Studio:运行安装程序,选择“使用C++的桌面开发”工作负载,然后点击“安装”。
- 创建项目:打开Visual Studio,选择“创建新项目”,然后选择“空项目”或“控制台应用程序”模板。
- 编写代码:在项目中创建源文件(.cpp),编写你的C++代码。
- 编译和运行:点击“生成”菜单中的“生成解决方案”来编译代码,然后点击“调试”菜单中的“开始执行(不调试)”或“开始调试”来运行程序。
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值表示出现错误。
编译和运行:
- 将代码保存为
.cpp
文件(如hello.cpp
)。 - 打开命令行或终端。
- 使用编译器编译代码:
- GCC/Clang:
g++ hello.cpp -o hello
或clang++ hello.cpp -o hello
- MSVC:
cl hello.cpp
- GCC/Clang:
- 运行生成的可执行文件:
- Linux/macOS:
./hello
- Windows:
hello.exe
- Linux/macOS:
你应该能在控制台看到输出: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 int
、unsigned short
、unsigned long
、unsigned 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++的关键字(如
int
、double
、if
、for
等)。 - 变量名区分大小写(
age
和Age
是不同的变量)。 - 建议变量名要有意义, 使用描述性的词语, 增加程序可读性.
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 + b
、x * 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])
**动态内存分配:**
cpp
使用`new`和`delete`运算符可以在运行时动态分配和释放内存。
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++编程技能。祝你学习顺利!