一、C++和C语言的区别
C++基本包含C语言的内容,简单理解就是C语言的升级。区别主要体现在以下几点:
1.1指针和引用
C++特有引用,在传递变量时由于引用指向的对象不能为空,所以可以避免空指针访问的问题。
1.2struct结构体
C 中的 struct 用来描述一种固定的内存组织结构,而 C++ 中的 struct 就是一种类,因此C中结构体的成员和继承行为默认是public的,而C++中是private的。
1.3宏和模板
C++之所以要设计模板就是为了更好地实现宏的功能,模板不同于宏的文字替换,在编译时会得到更全面的编译器检查,便于编写更健全的代码。
1.4const
const在C中只有限定变量不能修改的功能,而在C++中功能较为丰富。
1.5内存分配
C++中新增了new和delete关键字用来在“自由存储区”(堆或静态存储区)上分配空间,但效率不如malloc()函数。
二、C++基础
2.1Hello World
C++
#include <iostream>
using namespace std;
int main()
{
cout<<"Hello World"<<endl;
return 0;
}
2.2命名空间
命名空间就是为了解决一些重名问题。例如,std空间中有变量cin,如果自己定义了一个叫cin的变量,则可通过cin访问自定义的cin,通过std::cin访问标准库中的cin。
//定义了一个名称空间A,可以通过域作用符::访问A
namespace A {
int cin;
void fun() {
cin = 0;
}
}
//名称空间的声明可以嵌套
using指令
- using 名称空间::成员名,访问成员时可忽略命名空间
- using namepace 命名空间,访问命名空间下的所有成员时都可忽略命名空间
- 可能会导致命名冲突
2.3变量
变量的作用
给指定的内存空间取名,方便操作这段内存
语法:数据类型+变量名=初始值
//变量的类型
bool a1 ;//true/false,用于判断对错
int a2 ;//范围-2147483648~2147483648
char a3 ;//字符型 'a','\n'
float a4 ;//单精度
double a5 ;//双精度
long long a6 ;//长整型
long double a7 ;//长浮点型
string a8 ;//字符串型
定义变量的三个地方
-
局部变量:在函数或一个代码块内部声明的变量。
-
形式参数:在函数参数的定义中声明的变量。
-
全局变量:在所有函数外部声明的变量。
变量作用的四个区域
-
局部作用域:在函数内部声明的变量,只能在函数内部访问。局部变量在函数每次被调用时被创建,在函数执行完后被销毁。
-
全局作用域:在所有函数和代码块之外声明的变量,可以被程序中的任何函数访问。全局变量在程序开始时被创建,在程序结束时被销毁。
-
块作用域:在代码块内部声明的变量,只能在代码块内部访问。块作用域变量在代码块每次被执行时被创建,在代码块执行完后被销毁。
-
类作用域:在类内部声明的变量具有类作用域,它们可以被类的所有成员函数访问。类作用域变量的生命周期与类的生命周期相同。
2.4常量
常量:不可更改的数据
定义常量的两种方式
- const 修饰的变量: const+数据类型+常量名 = 常量值
- define宏常量:define+常量名+常量值
2.5输入和输出
- 输入:cin>>
- 输出:cout<<
2.关键字
C++中一些特别的单词,不能被定义
2.6标识符
标识符:变量/常量的名字
规则:
- 标识符不能是关键字
- 标识符只能由字母、数字、下划线组成,且不能以数字开头
- 命名时要见名知意,方便理解
三、数据类型
数据类型包括基础数据类型和符合数据类型。
3.1基础数据类型
-
无类型 void型
-
空指针类型 (C++11起)
-
算术类型
3.2算术类型
整型(整数)
- short 短整型 2字节
- int 整型 4字节
- long 长整型 4字节(Windows) 4/8字节(Linux (32/64位))
- long long 长长整型 8字节
浮点型(小数)
- float 单精度 4字节 7位有效数字
- double 双精度 8字节 15~16位有效数字
字符型(字符)
char 变量名 = '字符 '
字符型变量不是把字符放到内存中储存,而是把字符对应的ASCLL编码储存
字符串型
- char 变量名[ ] = " "
- string 变量名 = " "
布尔型 bool
- true 真
- false 假
3.3复合类型
- 数组类型
- 引用类型
- 指针类型
- 类类型
- 函数类型
3.4typedef 声明
typrdef+数据类型+名称,把这个数据类型取一个新的名字,常用于结构体。
3.5sizeof关键字
统计数据类型所占的内存大小
sizeof(类型/变量)
3.6转义字符
- 用于表示不能显示的ASCLL符
- \n 换行
- \\ 反斜杠\
- \t 水平制表符:补空格,与前面的字符相加一共8个
例如:
- 第一行输出6个a和2个空格
- 第一行输出5个a和3个空格
cout<<"aaaaaa\t"<<endl;
cout<<"aaaaa\t"<<endl;
3.7运算符
算术运算符
加减乘除
- +、-、 *
- / :
两个整数(不管什么数)相除,结果仍为整数
被除数不可为0
-
%(取余)
小数之间不能取余
++(递增) --(递减)
前置和后置的区别:
对于非表达式:没有区别
int a1=10;
int a2=10;
a1++;
++a2;
cout<<"a1="<<a1<<endl;
cout<<"a2="<<a2<<endl;
结果为:
对于表达式:
- 前置递增(++i): 先将变量i加1,然后返回加1后的结果。
- 后置递增(i++): 先返回变量i的原值,然后再将变量i加1。
int a1 = 10;
int a2 = 10;
int b1 = a1++ * 10;
int b2 = ++a2 * 10;
cout << "a1=" <<a1<< endl;
cout << "b1=" <<b1<< endl;
cout << "a2=" <<a2<< endl;
cout << "b2=" <<b2<< endl;
结果为:
算术运算中的类型转换
对于一个int型变量m和一个double型变量n:
- m/3 结果为整型
- m/3.0 结果为双精度浮点型
- m/n 结果为整型
- m*1/3结果为整型
- m*1.0/3结果为双精度浮点型
即都为整数,结果是整数,只要有浮点数,结果为浮点数。
赋值运算符
- =
- += a=1,b=2,a+=b -> a=3,b=2
- -=
- /=
- *=
- %=
比较运算符
==、!=、>=、<=、>、<
逻辑运算符
- &&与
- || 或
- !非
位运算符
四、程序流程结构
程序流程结构:
- 顺序结构:程序按照代码的先后顺序从上到下依次执行。
- 选择结构
- 循环结构
- 嵌套结构
4.1选择结构
if语句
- 单行if语句
- if-else语句
- 嵌套if语句
switch-case语句
根据变量的值选择执行不同的代码块。
switch(选择对象){
case 条件1 :
statement(s);
break; // 可选的
case 条件2 :
statement(s);
break; // 可选的
default : //不是以上条件
statement(s);
}
三目运算符
条件?表达式1:表达式2
- 如果条件的值为 true(非零值),则执行表达式1
- 如果条件的值为 false(零值),则执行表达式2
4.2循环结构
- while循环:只要满足循环条件就一直执行循环体。
while(condition)
{
statement(s);
}
- do-while循环:先执行一次循环体,然后再判断循环条件。
do
{
statement(s);
}while( condition );
- for循环:初始化、条件判断、循环体和迭代操作集中在一起。
for ( init; condition; increment )
{
statement(s);
}
- 先执行 init ,且只会执行一次。然后判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且直接跳转到下一语句。
- 接下来,执行循环主体,执行完 for 循环主体后,控制流会跳回上面的 increment (可以为空),语句条件再次被判断。
- 如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。
4.3嵌套结构
在一个控制结构中嵌套另一个控制结构,形成多层的控制结构。
4.4循环控制语句
break语句
- 当 break 语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。
- 它可用于终止 switch 语句中的一个 case。
continue语句
跳过当前循环中的代码,强迫开始下一次循环。
int a = 10;
do
{
if( a == 15)
{
a = a + 1;
continue;
}
cout << "a 的值:" << a << endl;
a = a + 1;
}while( a < 20 );
结果:
goto语句
int a = 10;
LOOP:do
{
if( a == 15)
{
// 跳过迭代
a = a + 1;
goto LOOP;
}
cout << "a 的值:" << a << endl;
a = a + 1;
}while( a < 20 );
五、高级数据类型
5.1数组
数组是存放一系列相同类型变量的容器,其空间是连续的。
一维数组
声明:
- 数据类型+数组名[数量];
- 数据类型+数组名[数量]={元素1,元素2,…………};
- 数据类型+数组名[]={元素1,元素2,…………};
访问
不同于一般变量有自己的名字,数组里的元素没有自己的名字,但数组是一段连续的空间,我们可以通过位置来访问。
数组名[元素的序号];(元素的序号从0开始)
二维数组和多维数组
数据类型 数组名称[m][n]; 创建一个m行n列的二维数组,相当于一个平面。
数组在内存中的储存:
可以把内存理解为一个队伍,二维数组存储数据可以理解为一个方阵去一行一行地去排队,内存的偏移与数据类型有关。
多维数组也是如此,如三维数组可以理解为一个立方体……
5.2结构体
比起C语言中的结构体,C++中的结构体不仅有其功能,还有类的一些功能,如成员函数,继承,多态等。
详细见C语言基础和面向对象。
5.3联合体(共用体)
共用体,和C一样。
特点
- 共用体的大小只取决于最大的成员的大小。
- 共用体的成员共享同一块内存空间,只能同时存储其中一个成员的值。
- 对共用体的任何成员的修改都会影响到其他成员。
- 共用体的成员可以具有不同的数据类型,但它们在内存中的起始位置是相同的。
#include<stdio.h>
#include<string.h>
union stu {
char a1;
short a2;
int a3;
};
int main() {
union stu s1;
memset(&s1, 0, sizeof(s1));
printf("sizeof: %d\n", sizeof(s1));
s1.a1 = '1';
printf("a2: %c\na3: %c", s1.a2, s1.a3);
return 0;
}
结果为
用途
- 节省内存空间:当多个成员变量不会同时使用,但需要共享同一块内存空间时,可以使用共用体来节省内存。
- 数据类型转换:共用体可以用于不同类型之间的转换,通过存储一个成员变量,然后通过另一个成员变量来读取转换后的值。
5.4指针
基础用法见C语言基础。
C语言和C++中指针的区别:
指针类型的转换
- C:(类型
*
)强转 - C++:
static_cast<类型 *>()
进行更安全的类型转换,增加了代码的可读性和安全性。
引用
C++中有引用这一变量访问方式
指针算术
C++在指针算术上提供了更多的边界检查和类型安全的特性。
智能指针
C++提供了智能指针,如std::unique_ptr
、std::shared_ptr
和std::weak_ptr
,这些指针类型帮助管理动态分配的内存,自动释放资源,防止内存泄漏。
四、函数
基础用法见C语言基础。
C语言和C++中函数的区别
函数重载
C++支持函数重载,即可以有多个同名函数,只要它们的参数类型或参数数量不同即可。编译器会根据调用时提供的参数来决定使用哪个函数。
默认参数
C++支持默认参数,可以在函数声明时为参数指定默认值,这样在调用函数时可以省略这些参数
内联函数
C++支持内联函数。可以使用inline
关键字声明内联函数,编译器会尝试将这些函数的代码直接插入到每个调用点,以减少函数调用的开销。内联函数在编译时进行类型检查。
五、文件操作
文件:根据特定的目的而收集在一起的有关数据的集合,比如文本、图片、视频、程序代码等任何形式的数据。
C++把每个文件当作一个数据流(一组以连续方式流动的数据项序列),每个文件都有文件结束标志。有文本文件和二进制文件两种。
文件操作步骤:
- 打开文件
- 读取文件
- 写入文件
- 关闭文件
freopen函数
FILE* freopen(const char* filename, const char* mode, FILE* stream);
参数
- filename:要打开的文件名
- mode:打开的格式
- stream:文件指针,使用标准文件流(stdin和stdout)或标准错误输出流(stderr)
- 返回值是文件指针,指向被打开的文件,如果失败则返回NULL
打开格式:
"r"
(只读)
"w"
(只写,会清空文件内容)
"a"
(追加,写操作会从文件末尾开始)
"r+"
(读/写)
"w+"
(读/写,会清空文件内容)
"a+"
(读/写,写操作会从文件末尾开始)
//读入文件
freopen("data.in", "r", stdin);
//输出文件
freopen("data.out", "w", stdout);
//关闭文件标准输入/输出流
fclose(stdin);
fclose(stdout);
ifstream和ofstream文件输入输出流
//读入文件
ifstream fin("data.in");
//输出到文件
ofstream fout("data.out");
//关闭标准输入/输出流
fin.close();
fout.close();