1 c++的空间开辟和释放

1.1 c++的空间开辟

C++中开辟空间不同于c语言。他为我们提供了更加便利的空间开辟方式——new运算符。

基本格式如下

1
int*p=new int(10);

上述代码意思是开辟一块10个空间为整数存放。==注意:这里是开辟10个字节的整形空间,可以理解为开始10个字节空间是存储整形的,并非10个整形空间==

而在c语言中是这样的

1
int* p=(int*)malloc(10);

相比之下,c++对其代码和结构做了更多优化。

那么开辟10个整形空间大小就用如下方式

1
int*p=new[10];

这里就开辟了10个整形大小空间,即10*4个字节大小。(开辟了一个数组)

在c语言中是这样的

1
int*p=(int*)mallooc(sizeof(int)*10);

==注意:如果开辟10个字节我们用的是”()“小括号,如果是10个整形空间,我们就用的是“”[]”中括号==

c++中仿照数组的命名形式将其优化,使得代码更加高效。


1.2 c++的空间释放

在空间的释放中,c与c++也有着不同之处

c++的空间如果是第一种用int(10)声明的那么释放如下

1
delete p;

c语言中如下

1
free (p);

如果是c++中声明了一个数组则是

1
delete [] p;

==注意:这里则是在其中加一个中括号才可以完全释放数组,否则只会释放首元素的地址空间==

在c语言中

1
free(p);

依旧是如此就可以了。

那么这里我们可以理解为c语言中只是进行了一个地址分配了4*10个空间,而c++中则是分配了10个int类型的地址空间。

**c语言中,目前只有c99标准可以使用动态参数定义数组,否则就需要用malloc申请动态空间去定义自定义数组。**c++对其进行了优化。


2. c++的引用

在c++中有个引用的方式,可以理解为为一个空间起多个变量名字,基本格式如下

1
2
int a=10;
int &b=a;

此时就完成了引用。那么当我们输出b和a时如下

image-20231130164320509

那么这里与直接将a的值赋值给b有什么区别呢?我们说这里我们是给a的地址起了个别名,就意味着,我们对b的操作是可以影响到a的。看以下示例

1
2
3
4
5
6
int a=10;
int &b=a;

b=20;
cout<<"a的值为:"<<a<<endl;
cout<<"b的值为:"<<b<<endl;

输出结果如下

image-20231130164607558

我们可以发现,b的操作可以影响到a。所以与a直接赋值给b是有区别的。这里对b的赋值操作直接影响了a。

在使用引用时要注意以下几点:

  1. 引用必须初始化,即声明时就要将其赋值。
  2. 引用初始化后不可改变(我们可以看见b=20时只是改变了地址对应的空间存储的值)。
  3. 引用时不可以用数值直接赋值(常量引用可以)。
  4. 在引用函数中,不要将局部变量返回出来(因为函数中的局部变量在函数结束时会销毁)

引用的本质:

引用实际上是常量指针的形式,也就解释了为什么引用的操作可以影响原空间并且引用初始化后不可以更改引用的对象了。

在上述例子中我们可以有如下分析

1
2
3
int a=10;
int&b=a;//这里即为int* const b=&a;
b=20;//可以理解为 *b=20;

那么在函数中,引用的作用是方便修改实参。优点在于简化了指针修改实参。

引用中也有常量引用,即用const修饰,==常量引用最大的作用是防止误操作,因为引用会对原数据造成修改,在引用时需要保护起来,一半用于函数的参数传递,防止修改了其值。==

例子

1
2
3
4
5
6
7
8
9
10
void print(const int&b)
{
cout<<"b的值为:"<<b<<endl;

}
int main(){
int a=14;
int &b=a;
print(&b);
}

除此之外还有另一种用法const修饰的引用可以直接使用赋值

示例如下

1
2
const int &b=10;
cout<<"b的值为:"<<b<<endl;

输出结果为

image-20231130171534435

其原理可以拆成如下方式

1
2
3
4
const int &b=10;
//分为两步
//第一步,系统会自动创建一个变量int temp=10(名字我们不知道,temp只是做举例)
//第二步,系统再执行const int &b=temp;

3. c++函数及其用法

3.1 函数默认参数

在c++中的函数是有默认参数的

下面为例子

1
2
3
4
5
6
7
8
9
int add(int a,int b=20){
return a+b;
}


int main() {
cout<<"a+b="<<add(10)<<endl;//第一个输出
cout<<"a+b="<<add(10,40)<<endl;//第二个输出
}
  • 将b直接赋值,在调用用函数时只传进去一个数,那么他就会默认给形参a赋值。(第一个输出),然后20就是b的默认参数

  • 那么当我们传入两个数值时40便会覆盖b的20(第二个输出)。

注意:

  1. 当我们设置了默认参数后,此参数以后的参数都必须设置默认参数
  2. 默认参数在声明和函数定义时只能设置一次,即声明和定义中只能有一个有默认参数。

3.2 函数的占位参数

c++中函数可有有占位参数,用来占位使用。

基本语法结构为

1
2
3
int func(int a,int){//此处第二个参数只有类型的为占位参数
cout<<"text"<<endl;
}

并且占位参数也可以有默认参数

1
2
3
int func(int a,int = 10){//此处第二个参数只有类型的为占位参数并且不需要名字直接可以赋值默认值
cout<<"text"<<endl;
}

注意:默认参数调用时必须传入数据


3.3 函数重载

即函数名可以相同(c语言不具备此重要性质)

优点:可以提高复用性

函数重载条件:

  1. 同一个作用域下。
  2. 函数名称相同
  3. 函数参数的 类型不同 或者 个数不同或者 顺序不同

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int func(int a){
cout<<"this is a text"<<endl;
}
int func(float a){
cout<<"this is a text"<<endl;
}

int func(int a,int b){
cout<<"this is a text"<<endl;
}

int func(int b,int a){
cout<<"this is a text"<<endl;
}

引用参数的函数示例

1
2
3
4
5
6
7
int func(int&a){//调用此参数时需要传入变量名
cout<<"this is a text"<<endl;
}

int func(const int &a){//调用此函数时需要直接传入数值
cout<<"this is a text"<<endl;
}

==注意:函数重载时尽量不要写默认参数,不然容易出现歧义。==

如下==反例==

1
2
3
4
5
6
7
8
int func(int a,int b=10){
cout<<"this is a text"<<endl;
}

int func(int a){
cout<<"this is a text"<<endl;
}

如上当我们只传递一个数值时会分不清使用哪个函数,所以会报错。(但是如果传入两个值会执行第一个函数)


资料参考

b站的黑马程序员