四区
首先,我们要先了解C++中的内存四区即:代码区、全局区、栈区、堆区。
代码区:存放函数体的二进制代码,由操作系统进行管理。
全局区:存放全局变量和静态变量以及常量。
栈区:由编译器自动分配和释放存放函数的参数值,局部变量等。
堆区:由程序员分配和释放,如果程序员不释放,程序结束后由操作系统回收。
前面两个区是属于程序运行前的,后两个是在程序运行后才有的。
全局区
主要存放全局变量和static修饰的变量,还有常量,常量有分为”字符串常量“和”const修饰的全局变量“,注意:const修饰的局部变量不在全局区中,而static修饰的变量都在全局区中。
栈区
关于栈区要注意,不能返回局部变量的地址。
int *func()
{
int a = 10;
return &a;
}
因为局部变量是存放在栈区,在函数被执行完后就会被销毁。
堆区
接下来我们将认识
一个新的关键字new(可以与C中的malloc类比),利用new我们可以将数据开辟到堆区。new会返回数据存放的地址。
int *func()
{
int *a = new int(10);
return a;
}
int *a = new int(10); //指针本质上其实是局部变量,放在栈区,但是其保存的数据放在堆区。
int *func()
{
int p = 10;
int *a = &p;
return a;
}
如上,此时数据存放在栈区,函数结束后会被释放。
new关键字
现在我们深入了解一下关键字new
堆区的数据由程序员开辟,当然也由程序员释放
即用delete关键字释放。
当然,我们也可以在堆区开辟数组
void arr()
{
int *arr = new int[10]//开辟一个10个整型数据的数组
//释放方法
delete [] arr;
}
方法总结:
存放一个数据:
int *p = new int(10);
删除一个数据:
delete p;
存放一个数组:
int *arr = new int[10];
删除一个数组:
delete [] arr;
引用
实际上引用就是一个指针常量。
下面我们就先来熟悉一下指针常量和常量指针。
指针常量
这一概念我们通过代码进行认识
//1.const修饰指针 常量指针
int a = 10;
int b = 10;
const int *p = &a;
// *p = b;不可以
*p = &b;
在常量指针下指针的指向可以改,但是指针指向的值不可以改,例如上述代码,我们是无法修改p指针所指向的值的,而我们可以将指针p指向b的地址。注意:就算指针p指向了b的地址也是无法对b的值进行修改的。
常量指针
//2.const修饰常量
int *const p2 = &a;//指针的指向不可以改
//p = &b
*p2 = 20;
而常量指针则相反,我们无法修改常量指针的指向,但我们可以修改其指向的值。
还有一种是两者的结合。
//3.const修饰指针和常量
const int * const p3 = &a;//两者都不可以改
这种我们两者都无法修改。
引用的使用方法
引用可看作给变量取的别名
int a;
int &b = a;
如上,b就相当于a的另一个名字
示例:
#intclude<iostream>
using namespace std;
int main()
{
int a = 10;
int &ref = a;
cout << "a=" << a <<endl;
cout << "ref=" << ref <<endl;
ref = 100;
cout << "a=" << a <<endl;
cout << "ref=" << ref <<endl;
system("pause");
reutrn 0;
}
引用的注意事项
引用必须初始化。
引用在初始化后,就不可改变。
我们不可以直接int &b; 引用的时候必须初始化。
int main(){
//int &b;(错误)
int a=10;
int &b = a;
int c = 20;
b = c;//这个含义并不是让b成为c的别名,而是赋值操作
}
引用做函数参数
函数传参时,我们可以利用引用实现指针修改实参的效果
示例:
void Myswap2(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void Myswap3(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
两者的效果是相同的,使用引用我们可以简化指针传参的操作。
引用做函数的返回值
#include<iostream>
using namespace std;
//引用做函数的返回值
int &test01()
{
int a = 10;
return a;
}
int main()
{
int &ref = test01();
cout<<ref<<endl;
cout<<ref<<endl;
system("pause");
return 0;
}
上面的代码是错误的,因为a是局部变量,当函数被执行完了就会被编译器释放。那我们要如何实现呢?
#include<iostream>
using namespace std;
//引用做函数的返回值
int &test01()
{
static int a = 10;
return a;
}
int main()
{
int &ref = test01();
cout<<ref<<endl;
cout<<ref<<endl;
system("pause");
return 0;
}
我们将a改为静态变量,这样a就存在全局区,由系统进行释放操作,只有程序运行完了才会被释放。
还有一个补充的点:函数的调用可以作为左值。
#include<iostream>
using namespace std;
//引用做函数的返回值
int &test01()
{
static int a = 10;
return a;
}
int main()
{
int &ref = test01();
cout<<ref<<endl;
cout<<ref<<endl;
test01() = 100;//函数的调用可以作为左值。
cout<<ref<<endl;
cout<<ref<<endl;
system("pause");
return 0;
}
引用的本质
引用的本质在C++相当于一个指针常量
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int &b = a;//相当于 int const *b = &a;
b = 100;//相当于 *b = 100;
}
ok,完工!!!!