C++ 学习_基础知识
一直想学习 C++ 这门编程语言,但感觉 C 总是没学牢靠一拖再拖,这几天根据网上教程,准备快速过下 C++ 基本语法。
对于我来说,直接看文档自学,往往比看视频效率高些,相信有了 C 基础,C++ 的学习应该会轻松些。
一、C++ 教程

#include <iostream> // iostream 输入输出流 头文件
using namespace std; // C++ 命名空间
int main()
{cout << "Hello World!" << endl; // cout 输出语句 endl 换行 可以用 \n 代替cout << "Hello World!" << "\n"; return 0;
}//易错:endl 中最后一个是字母小写L // 输出:
// Hello World!
// Hello World!
关于 C++ 命名空间说明:
在c++中,名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象等等。工程越大,名称互相冲突性的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突。为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入关键字namespace(命名空间/名字空间/名称空间),可以更好地控制标识符的[作用域]。
命名空间的使用,代码示例如下:
//定义一个名字为A的命名空间(变量、函数)
namespace A {int a = 100;
}
namespace B {int a = 200;
}
void test02()
{//A::a a是属于A中cout<<"A中a = "<<A::a<<endl;//100cout<<"B中a = "<<B::a<<endl;//200
}
既然是初学,就暂时不要深入探讨了,后来再慢慢补上。
二、C++ 简介
C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。
C++ 被认为是一种中级语言,它综合了高级语言和低级语言的特点。
C++ 是由 Bjarne Stroustrup 于 1979 年在新泽西州美利山贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,最初命名为带类的C,后来在 1983 年更名为 C++。
C++ 是 C 的一个超集,事实上,任何合法的 C 程序都是合法的 C++ 程序。
注意:使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。
1、面向对象程序设计
C++ 完全支持面向对象的程序设计,包括面向对象开发的四大特性:
- 封装(Encapsulation):封装是将数据和方法组合在一起,对外部隐藏实现细节,只公开对外提供的接口。这样可以提高安全性、可靠性和灵活性。
- 继承(Inheritance):继承是从已有类中派生出新类,新类具有已有类的属性和方法,并且可以扩展或修改这些属性和方法。这样可以提高代码的复用性和可扩展性。
- 多态(Polymorphism):多态是指同一种操作作用于不同的对象,可以有不同的解释和实现。它可以通过接口或继承实现,可以提高代码的灵活性和可读性。
- 抽象(Abstraction):抽象是从具体的实例中提取共同的特征,形成抽象类或接口,以便于代码的复用和扩展。抽象类和接口可以让程序员专注于高层次的设计和业务逻辑,而不必关注底层的实现细节。
2、标准库
标准的 C++ 由三个重要部分组成:
- 核心语言,提供了所有构件块,包括变量、数据类型和常量,等等。
- C++ 标准库,提供了大量的函数,用于操作文件、字符串等。
- 标准模板库(STL),提供了大量的方法,用于操作数据结构等。
3、ANSI 标准
ANSI 标准是为了确保 C++ 的便携性 —— 您所编写的代码在 Mac、UNIX、Windows、Alpha 计算机上都能通过编译。
由于 ANSI 标准已稳定使用了很长的时间,所有主要的 C++ 编译器的制造商都支持 ANSI 标准。
4、学习 C++
学习 C++,关键是要理解概念,而不应过于深究语言的技术细节。
学习程序设计语言的目的是为了成为一个更好的程序员,也就是说,是为了能更有效率地设计和实现新系统,以及维护旧系统。
C++ 支持多种编程风格。您可以使用 Fortran、C、Smalltalk 等任意一种语言的编程风格来编写代码。每种风格都能有效地保证运行时间效率和空间效率。
5、C++ 的使用
C++ 语言在许多行业和领域都有广泛应用,包括:
- 游戏开发:C++ 是游戏开发领域中最常用的编程语言之一,因为它具有高效的性能和直接控制硬件的能力。许多主要的游戏引擎,如 Unreal Engine 和 Unity,都使用 C++ 编写。
- 嵌入式系统开发:C++ 可以在嵌入式系统中发挥重要作用,如智能手机、汽车、机器人和家电等领域。由于嵌入式系统通常具有严格的资源限制和实时要求,因此 C++ 的高效性能和内存控制功能非常有用。
- 金融领域:C++ 在金融领域中被广泛应用,如高频交易、算法交易和风险管理等领域。由于这些应用程序需要高效的性能和对硬件的直接控制,C++ 语言是一个合适的选择。
- 图形图像处理:C++ 可以用于开发图形和图像处理应用程序,如计算机视觉、计算机图形学和人工智能领域。由于这些应用程序需要高效的计算能力和对硬件的控制,因此 C++ 是一个很好的选择。
- 科学计算和数值分析:C++ 可以用于开发科学计算和数值分析应用程序,如数值模拟和高性能计算等领域。由于这些应用程序需要高效的计算能力和对硬件的直接控制,C++ 语言是一个很好的选择。
三、C++ 基本语法
C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。
- 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。
- 类 - 类可以定义为描述对象行为/状态的模板/蓝图。
- 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。
- 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。
1、C++ 程序结构
让我们看一段简单的代码,可以输出单词 Hello World。
#include <iostream>using namespace std;// main() 是程序开始执行的地方int main()
{cout << "Hello World"; // 输出 Hello Worldreturn 0;
}// 输出:
// Hello World
接下来我们讲解一下上面这段程序:
- C++ 语言定义了一些头文件,这些头文件包含了程序中必需的或有用的信息。上面这段程序中,包含了头文件
。 - 下一行 using namespace std; 告诉编译器使用 std 命名空间。命名空间是 C++ 中一个相对新的概念。
- 下一行 // main() 是程序开始执行的地方 是一个单行注释。单行注释以 // 开头,在行末结束。
- 下一行 int main() 是主函数,程序从这里开始执行。
- 下一行 cout << "Hello World"; 会在屏幕上显示消息 "Hello World"。
- 下一行 return 0; 终止 main( )函数,并向调用进程返回值 0。
2、C++ 注释
程序的注释是解释性语句,您可以在 C++ 代码中包含注释,这将提高源代码的可读性。所有的编程语言都允许某种形式的注释。
C++ 支持单行注释和多行注释。注释中的所有字符会被 C++ 编译器忽略。
C++ 注释一般有两种:
- // - 一般用于单行注释。
- /*** ... */** - 一般用于多行注释。
注释以 // 开始,直到行末为止。这部分内容和 C 语言一样。
四、C++ 数据类型
使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。
您可能需要存储各种数据类型(比如字符型、宽字符型、整型、浮点型、双浮点型、布尔型等)的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么。
1、基本的内置类型
C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型。下表列出了七种基本的 C++ 数据类型:
| 类型 | 关键字 |
|---|---|
| 布尔型 | bool |
| 字符型 | char |
| 整型 | int |
| 浮点型 | float |
| 双浮点型 | double |
| 无类型 | void |
| 宽字符型 | wchar_t |
其实 wchar_t 是这样来的:
typedef short int wchar_t;
所以 wchar_t 实际上的空间是和 short int 一样。
一些基本类型可以使用一个或多个类型修饰符进行修饰:
| 修饰符 | 描述 | 示例 |
|---|---|---|
signed |
表示有符号类型(默认) | signed int x = -10; |
unsigned |
表示无符号类型 | unsigned int y = 10; |
short |
表示短整型 | short int z = 100; |
long |
表示长整型 | long int a = 100000; |
const |
表示常量,值不可修改 | const int b = 5; |
volatile |
表示变量可能被意外修改,禁止编译器优化 | volatile int c = 10; |
mutable |
表示类成员可以在 const 对象中修改 |
mutable int counter; |
下表显示了各种变量类型在内存中存储值时需要占用的内存,以及该类型的变量所能存储的最大值和最小值。
注意:不同系统会有所差异,一字节为 8 位。
注意:默认情况下,int、short、long都是带符号的,即 signed。
注意:long int 8 个字节,int 都是 4 个字节,早期的 C 编译器定义了 long int 占用 4 个字节,int 占用 2 个字节,新版的 C/C++ 标准兼容了早期的这一设定。
| 数据类型 | 描述 | 大小(字节) | 范围/取值示例 |
|---|---|---|---|
bool |
布尔类型,表示真或假 | 1 | true 或 false |
char |
字符类型,通常用于存储 ASCII 字符 | 1 | -128 到 127 或 0 到 255 |
signed char |
有符号字符类型 | 1 | -128 到 127 |
unsigned char |
无符号字符类型 | 1 | 0 到 255 |
wchar_t |
宽字符类型,用于存储 Unicode 字符 | 2 或 4 | 取决于平台 |
char16_t |
16 位 Unicode 字符类型(C++11 引入) | 2 | 0 到 65,535 |
char32_t |
32 位 Unicode 字符类型(C++11 引入) | 4 | 0 到 4,294,967,295 |
short |
短整型 | 2 | -32,768 到 32,767 |
unsigned short |
无符号短整型 | 2 | 0 到 65,535 |
int |
整型 | 4 | -2,147,483,648 到 2,147,483,647 |
unsigned int |
无符号整型 | 4 | 0 到 4,294,967,295 |
long |
长整型 | 4 或 8 | 取决于平台 |
unsigned long |
无符号长整型 | 4 或 8 | 取决于平台 |
long long |
长长整型(C++11 引入) | 8 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
unsigned long long |
无符号长长整型(C++11 引入) | 8 | 0 到 18,446,744,073,709,551,615 |
float |
单精度浮点数 | 4 | 约 ±3.4e±38(6-7 位有效数字) |
double |
双精度浮点数 | 8 | 约 ±1.7e±308(15 位有效数字) |
long double |
扩展精度浮点数 | 8、12 或 16 | 取决于平台 |
2、C++11 新增类型
| 数据类型 | 描述 | 示例 |
|---|---|---|
auto |
自动类型推断 | auto x = 10; |
decltype |
获取表达式的类型 | decltype(x) y = 20; |
nullptr |
空指针常量 | int* ptr = nullptr; |
std::initializer_list |
初始化列表类型 | std::initializer_list<int> list = {1, 2, 3}; |
std::tuple |
元组类型,可以存储多个不同类型的值 | std::tuple<int, float, char> t(1, 2.0, 'a'); |
注意,各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主。
以下列出了32位系统与64位系统的存储大小的差别(windows 相同):
从上表可得知,变量的大小会根据编译器和所使用的电脑而有所不同。
下面实例会输出您电脑上各种数据类型的大小。
#include <iostream>
#include <limits>using namespace std;int main()
{cout << "type:\t\t" << "********size*********" << endl;cout << "bool:\t\t" << "所占字节数:" << sizeof(bool);cout << "\t最大值:" << (numeric_limits<bool>::max)();cout << "\t\t最小值:" << (numeric_limits<bool>::min)() << endl;cout << "char:\t\t" << "所占字节数:" << sizeof(char);cout << "\t最大值:" << (numeric_limits<char>::max)();cout << "\t\t最小值:" << (numeric_limits<char>::min)() << endl;cout << "signed char:\t\t" << "所占字节数:" << sizeof(signed char);cout << "\t最大值:" << (numeric_limits<signed char>::max)();cout << "\t\t最小值:" << (numeric_limits<signed char>::min)() << endl;cout << "wchar_t:\t\t" << "所占字节数:" << sizeof(wchar_t);cout << "\t最大值:" << (numeric_limits<wchar_t>::max)();cout << "\t\t最小值:" << (numeric_limits<wchar_t>::min)() << endl;cout << "short:\t\t" << "所占字节数:" << sizeof(short);cout << "\t最大值:" << (numeric_limits<short>::max)();cout << "\t\t最小值:" << (numeric_limits<short>::min)() << endl;cout << "short:\t\t" << "所占字节数:" << sizeof(int);cout << "\t最大值:" << (numeric_limits<int>::max)();cout << "\t\t最小值:" << (numeric_limits<int>::min)() << endl;cout << "unsigned:\t\t" << "所占字节数:" << sizeof(unsigned);cout << "\t最大值:" << (numeric_limits<unsigned>::max)();cout << "\t\t最小值:" << (numeric_limits<unsigned>::min)() << endl;cout << "long:\t\t" << "所占字节数:" << sizeof(long);cout << "\t最大值:" << (numeric_limits<long>::max)();cout << "\t\t最小值:" << (numeric_limits<long>::min)() << endl;cout << "unsigned long:\t\t" << "所占字节数:" << sizeof(unsigned long);cout << "\t最大值:" << (numeric_limits<unsigned long>::max)();cout << "\t\t最小值:" << (numeric_limits<unsigned long>::min)() << endl;cout << "double:\t\t" << "所占字节数:" << sizeof(double);cout << "\t最大值:" << (numeric_limits<double>::max)();cout << "\t\t最小值:" << (numeric_limits<double>::min)() << endl;cout << "long double:\t\t" << "所占字节数:" << sizeof(long double);cout << "\t最大值:" << (numeric_limits<long double>::max)();cout << "\t\t最小值:" << (numeric_limits<long double>::min)() << endl;cout << "float:\t\t" << "所占字节数:" << sizeof(float);cout << "\t最大值:" << (numeric_limits<float>::max)();cout << "\t\t最小值:" << (numeric_limits<float>::min)() << endl;cout << "size_t:\t\t" << "所占字节数:" << sizeof(size_t);cout << "\t最大值:" << (numeric_limits<size_t>::max)();cout << "\t\t最小值:" << (numeric_limits<size_t>::min)() << endl;cout << "string:\t\t" << "所占字节数:" << sizeof(string);cout << "\t最大值:" << (numeric_limits<string>::max)();cout << "\t\t最小值:" << (numeric_limits<string>::min)() << endl;cout << "type:\t\t" << "********size*********" << endl;return 0;
}// :: 相当于 的

3、派生数据类型
| 数据类型 | 描述 | 示例 |
|---|---|---|
数组 |
相同类型元素的集合 | int arr[5] = {1, 2, 3, 4, 5}; |
指针 |
存储变量内存地址的类型 | int* ptr = &x; |
引用 |
变量的别名 | int& ref = x; |
函数 |
函数类型,表示函数的签名 | int func(int a, int b); |
结构体 |
用户定义的数据类型,可以包含多个不同类型的成员 | struct Point { int x; int y; }; |
类 |
用户定义的数据类型,支持封装、继承和多态 | class MyClass { ... }; |
联合体 |
多个成员共享同一块内存 | union Data { int i; float f; }; |
枚举 |
用户定义的整数常量集合 | enum Color { RED, GREEN, BLUE }; |
4、类型别名
| 别名 | 描述 | 示例 |
|---|---|---|
typedef |
为现有类型定义别名 | typedef int MyInt; |
using |
为现有类型定义别名(C++11 引入) | using MyInt = int; |
5、标准库类型
| 数据类型 | 描述 | 示例 |
|---|---|---|
std::string |
字符串类型 | std::string s = "Hello"; |
std::vector |
动态数组 | std::vector<int> v = {1, 2, 3}; |
std::array |
固定大小数组(C++11 引入) | std::array<int, 3> a = {1, 2, 3}; |
std::pair |
存储两个值的容器 | std::pair<int, float> p(1, 2.0); |
std::map |
键值对容器 | std::map<int, std::string> m; |
std::set |
唯一值集合 | std::set<int> s = {1, 2, 3}; |
6、typedef 声明
您可以使用 typedef 为一个已有的类型取一个新的名字。下面是使用 typedef 定义一个新类型的语法:
typedef type newname;
例如,下面的语句会告诉编译器,feet 是 int 的另一个名称:
typedef int feet;
现在,下面的声明是完全合法的,它创建了一个整型变量 distance:
feet distance;
7、枚举类型
枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。
如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。
创建枚举,需要使用关键字 enum。枚举类型的一般形式为:
enum 枚举名{ 标识符[=整型常数], 标识符[=整型常数],
... 标识符[=整型常数]
} 枚举变量;
如果枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始。
例如,下面的代码定义了一个颜色枚举,变量 c 的类型为 color。最后,c 被赋值为 "blue"。
enum color { red, green, blue } c;
c = blue;
默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。但是,您也可以给名称赋予一个特殊的值,只需要添加一个初始值即可。例如,在下面的枚举中,green 的值为 5。
enum color { red, green=5, blue };
在这里,blue 的值为 6,因为默认情况下,每个名称都会比它前面一个名称大 1,但 red 的值依然为 0。
8、类型转换
类型转换是将一个数据类型的值转换为另一种数据类型的值。
C++ 中有四种类型转换:静态转换、动态转换、常量转换和重新解释转换。
(1)静态转换
静态转换是将一种数据类型的值强制转换为另一种数据类型的值。
静态转换通常用于比较类型相似的对象之间的转换,例如将 int 类型转换为 float 类型。
静态转换不进行任何运行时类型检查,因此可能会导致运行时错误。
int i = 10;
float f = static_cast<float>(i); // 静态将int类型转换为float类型
(2)动态转换(暂且跳过)
动态转换(dynamic_cast)是 C++ 中用于在继承层次结构中进行向下转换(downcasting)的一种机制。
动态转换通常用于将一个基类指针或引用转换为派生类指针或引用。
动态转换在运行时进行类型检查。如果转换失败,对于指针类型会返回 nullptr,对于引用类型则会抛出 std::bad_cast 异常。
dynamic_cast<目标类型>(表达式)
- 目标类型:必须是指针或引用类型。
- 表达式:需要转换的基类指针或引用。
(3)常量转换
常量转换用于将 const 类型的对象转换为非 const 类型的对象。
常量转换只能用于转换掉 const 属性,不能改变对象的类型。
const int i = 10;
int& r = const_cast<int&>(i); // 常量转换,将const int转换为int
五、实训:编写计算器程序
// 学习文档注释,示例如下:/*** @brief 计算两个整数的和。** @param a [in] 第一个整数。* @param b [in] 第二个整数。* @return 返回两个整数的和。** @author wiro* @date 2025/12/15*/// 包含输入输出流头文件,用于 cout (输出) 和 cin (输入)#include <iostream>// 用于处理可能的输入错误 (可选,但更健壮)#include <limits>// 函数声明: 定义加法,减法,乘法,除法函数double add(double a,double b);double subtract(double a,double b);double multiply(double a,double b);double divide(double a,double b);int main()
{// 定义变量:存储两个操作数和运算符double num1,num2,result;char op;// 标记是否继续计算char continueFlag = 'y';// 循环:实现多次计算while (continueFlag == 'y' || continueFlag == 'Y'){// 这个程序没在前面定义命名空间,所以要加上 std::// std::cout 意思是 标准的输出// 提示用户输入std::cout << "===== 简易计算器 =====" << std::endl;std::cout << "请输入第一个数字:";std::cin >> num1; // 输入 num1 数值// 检查输入是否合法(比如输入非数字的情况)if (std::cin.fail()){std::cout << "输入错误!请输入有效数字。" << std::endl;// 清除输入错误状态std::cin.clear();// 忽略缓冲区中的无效字符std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');continue;}std::cout << "请输入运算符(+、-、*、/):";std::cin >> op;std::cout << "请输入第二个数字:";std::cin >> num2;// 检查输入是否合法(比如输入非数字的情况)if (std::cin.fail()){std::cout << "输入错误!请输入有效数字。" << std::endl;// 清除输入错误状态std::cin.clear();// 忽略缓冲区中的无效字符std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');continue;}// 条件判断:根据运算符选择对应的计算函数switch (op){case '+':result = add(num1,num2);std::cout << num1 << "+" << num2 << "=" << result << std::endl;break;case '-':result = subtract(num1,num2);std::cout << num1 << "-" << num2 << "=" << result << std::endl;break;case '*':result = multiply(num1,num2);std::cout << num1 << "*" << num2 << "=" << result << std::endl;break;case '/':// 除法特殊处理:除数不能为 0 if (num2 == 0){std::cout << "错误:除数不能为 0 !" << std::endl;}else{result = divide(num1,num2);std::cout << num1 << "/" << num2 << "=" << result << std::endl;}break;default:std::cout << "错误: 无效的运算符! " << std::endl;break;}// 询问是否继续计算std::cout << "是否继续计算?(y/n):";std::cin >> continueFlag;// 清空换行符,避免影响下一次输入std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');std::cout << "------------------------" << std::endl;}std::cout << "计算器已退出,感谢使用! " << std::endl;return 0;
}// 函数定义:加法
double add(double a,double b)
{return a + b;
}
// 函数定义:减法
double subtract(double a,double b)
{return a - b;
}
// 函数定义:乘法
double multiply(double a,double b)
{return a * b;
}
// 函数定义:除法
double divide(double a,double b)
{return a / b;
}
六、C++ 变量类型
变量其实只不过是程序可操作的存储区的名称。
在 C++ 中,有多种变量类型可用于存储不同种类的数据。
C++ 中每个变量都有指定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。
大写字母和小写字母是不同的,因为 C++ 是大小写敏感的。
基于前一章讲解的基本类型,有以下几种基本的变量类型,将在下一章中进行讲解:
| 类型 | 描述 |
|---|---|
| bool | 布尔类型,存储值 true 或 false,占用 1 个字节。 |
| char | 字符类型,用于存储 ASCII 字符,通常占用 1 个字节。 |
| int | 整数类型,通常用于存储普通整数,通常占用 4 个字节。 |
| float | 单精度浮点值,用于存储单精度浮点数。单精度是这样的格式,1 位符号,8 位指数,23 位小数,通常占用4个字节。![]() |
| double | 双精度浮点值,用于存储双精度浮点数。双精度是 1 位符号,11 位指数,52 位小数,通常占用 8 个字节。![]() |
| void | 表示类型的缺失。 |
| wchar_t | 宽字符类型,用于存储更大范围的字符,通常占用 2 个或 4 个字节。 |
C++ 也允许定义各种其他类型的变量,比如枚举、指针、数组、引用、数据结构、类等等,这将会在后续的章节中进行讲解。
- 整数类型(Integer Types):
int:用于表示整数,通常占用4个字节。short:用于表示短整数,通常占用2个字节。long:用于表示长整数,通常占用4个字节。long long:用于表示更长的整数,通常占用8个字节。
- 浮点类型(Floating-Point Types):
float:用于表示单精度浮点数,通常占用4个字节。double:用于表示双精度浮点数,通常占用8个字节。long double:用于表示更高精度的浮点数,占用字节数可以根据实现而变化。
- 字符类型(Character Types):
char:用于表示字符,通常占用1个字节。wchar_t:用于表示宽字符,通常占用2或4个字节。char16_t:用于表示16位Unicode字符,占用2个字节。char32_t:用于表示32位Unicode字符,占用4个字节。
- 布尔类型(Boolean Type):
bool:用于表示布尔值,只能取true或false。
- 枚举类型(Enumeration Types):
enum:用于定义一组命名的整数常量。
- 指针类型(Pointer Types):
type*:用于表示指向类型为type的对象的指针。
- 数组类型(Array Types):
type[]或type[size]:用于表示具有相同类型的元素组成的数组。
- 结构体类型(Structure Types):
struct:用于定义包含多个不同类型成员的结构。
- 类类型(Class Types):
class:用于定义具有属性和方法的自定义类型。
- 共用体类型(Union Types):
union:用于定义一种特殊的数据类型,它可以在相同的内存位置存储不同的数据类型。
在 C++ 中,类型的长度(即占用的字节数)取决于编译器和计算机架构,然而,C++ 标准规定了不同整数类型的最小范围,而不是具体的字节数,这是为了确保代码在不同的系统上都能正确运行。
请注意,以上类型的范围只是 C++ 标准规定的最小要求,实际上,许多系统上这些类型可能占用更多的字节,例如,很多现代计算机上 int 通常占用 4 字节,而 long 可能占用 8 字节。
下面我们将讲解如何定义、声明和使用各种类型的变量。
1、C++ 中的变量定义
变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。

变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示:
type variable_list;
在这里,type 必须是一个有效的 C++ 数据类型,可以是 char、wchar_t、int、float、double、bool 或任何用户自定义的对象,variable_list 可以由一个或多个标识符名称组成,多个标识符之间用逗号分隔。下面列出几个有效的声明:
int i, j, k;
char c, ch;
float f, salary;
double d;
行 int i, j, k; 声明并定义了变量 i、j 和 k,这指示编译器创建类型为 int 的名为 i、j、k 的变量。
变量可以在声明的时候被初始化(指定一个初始值)。初始化器由一个等号,后跟一个常量表达式组成,如下所示:
type variable_name = value;
下面列举几个实例:
extern int d = 3, f = 5; // d 和 f 的声明
int d = 3, f = 5; // 定义并初始化 d 和 f
byte z = 22; // 定义并初始化 z
char x = 'x'; // 变量 x 的值为 'x'
不带初始化的定义:带有静态存储持续时间的变量会被隐式初始化为 NULL(所有字节的值都是 0),其他所有变量的初始值是未定义的。
2、C++ 中的变量声明
变量声明向编译器保证变量以给定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。变量声明只在编译时有它的意义,在程序连接时编译器需要实际的变量声明。
当您使用多个文件且只在其中一个文件中定义变量时(定义变量的文件在程序连接时是可用的),变量声明就显得非常有用。您可以使用 extern 关键字在任何地方声明一个变量。虽然您可以在 C++ 程序中多次声明一个变量,但变量只能在某个文件、函数或代码块中被定义一次。
尝试下面的实例,其中,变量在头部就已经被声明,但它们是在主函数内被定义和初始化的:
#include <iostream>
using namespace std;// 声明变量
extern int a,b;
extern int c;
extern float f;int main()
{// 变量定义int a,b;int c;float f;// 实际初始化a = 10;b = 20;c = a + b;cout << f << endl;f = 70.0 / 3.0;cout << f << endl;return 0;
}// 输出:
// -5.09463e-35
// 23.3333
同样的,在函数声明时,提供一个函数名,而函数的实际定义则可以在任何地方进行。例如:
// 函数声明
int func();int main()
{// 函数调用int i = func();
}// 函数定义
int func()
{return 0;
}
3、C++ 中的左值和右值
C++ 中有两种类型的表达式:
- 左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
- 右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。下面是一个有效的语句:
int g = 20;
但是下面这个就不是一个有效的语句,会生成编译时错误:
10 = 20;
七、C++ 变量作用域
一般来说有三个地方可以定义变量:
- 在函数或一个代码块内部声明的变量,称为局部变量。
- 在函数参数的定义中声明的变量,称为形式参数。
- 在所有函数外部声明的变量,称为全局变量。
作用域是程序的一个区域,变量的作用域可以分为以下几种:
- 局部作用域:在函数内部声明的变量具有局部作用域,它们只能在函数内部访问。局部变量在函数每次被调用时被创建,在函数执行完后被销毁。
- 全局作用域:在所有函数和代码块之外声明的变量具有全局作用域,它们可以被程序中的任何函数访问。全局变量在程序开始时被创建,在程序结束时被销毁。
- 块作用域:在代码块内部声明的变量具有块作用域,它们只能在代码块内部访问。块作用域变量在代码块每次被执行时被创建,在代码块执行完后被销毁。
- 类作用域:在类内部声明的变量具有类作用域,它们可以被类的所有成员函数访问。类作用域变量的生命周期与类的生命周期相同。
注意:如果在内部作用域中声明的变量与外部作用域中的变量同名,则内部作用域中的变量将覆盖外部作用域中的变量。
1、局部变量
在函数或一个代码块内部声明的变量,称为局部变量。它们只能被函数内部或者代码块内部的语句使用。下面的实例使用了局部变量:
#include <iostream>
using namespace std;int main()
{// 局部变量声明int a,b;int c;// 实际初始化a = 10;b = 20;c = a + b;cout << c;return 0;
}// 输出:
// 30
2、全局变量
在所有函数外部定义的变量(通常是在程序的头部),称为全局变量。全局变量的值在程序的整个生命周期内都是有效的。
全局变量可以被任何函数访问。也就是说,全局变量一旦声明,在整个程序中都是可用的。下面的实例使用了全局变量和局部变量:
#include <iostream>
using namespace std;// 全局变量声明
int g;int main()
{// 局部变量声明int a,b;// 实际初始化a = 10;b = 20;g = a + b;cout << g;return 0;
}// 输出:
// 30
在程序中,局部变量和全局变量的名称可以相同,但是在函数内,局部变量的值会覆盖全局变量的值。下面是一个实例:
#include <iostream>
using namespace std;// 全局变量声明
int g = 20;int main()
{// 局部变量声明int g = 10;cout << g;return 0;
}// 输出:
// 10
3、初始化局部变量和全局变量
当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化。定义全局变量时,系统会自动初始化为下列值:
| 数据类型 | 初始化默认值 |
|---|---|
| int | 0 |
| char | '\0' |
| float | 0 |
| double | 0 |
| pointer | NULL |
正确地初始化变量是一个良好的编程习惯,否则有时候程序可能会产生意想不到的结果。
块作用域指的是在代码块内部声明的变量:
#include <iostream>int main()
{int a = 10;{int a = 20; // 块作用域变量std::cout << "块变量:" << a << std::endl; }std::cout << "外部变量:" << a << std::endl;return 0;
}// 输出:
// 块变量:20
// 外部变量:10
4、类作用域
类作用域指的是在类内部声明的变量:
#include <iostream>class MyClass
{public:static int class_var; // 类作用域变量
};int MyClass::class_var = 30;int main()
{std::cout << "类变量:" << MyClass::class_var << std::endl;return 0;
}// 输出:
// 类变量:30
以上实例中,MyClass 类中声明了一个名为 class_var 的类作用域变量。可以使用类名和作用域解析运算符 :: 来访问这个变量。在 main() 函数中访问 class_var 时输出的是 30。
写在最后
只能说 C++ 大部分语法结构 和 C 高度相似,有了 C 基础这些学的很快。
补个视频地址,不懂的看视频:第一章-05_变量的特征_哔哩哔哩_bilibili



