内存分区和函数调用
内存分区
C++中内存分为四区:代码区、全局区、栈区和堆区。
分区 | 存放 | 开辟 | 释放 |
---|---|---|---|
代码区 | 二进制代码 | 程序运行前、编译后 | 操作系统 |
全局区 | 全局变量、全局常量(字符串和const修饰) | 程序运行前、编译后 | 操作系统 |
栈区 | 局部变量、局部常量(字符串和const修饰) | 程序运行后 | 程序结束后,由编译器自动分配释放 |
堆区 | new开辟的空间 | 程序运行后 | 程序结束后,需要程序员delete手动释放 |
new举例
使用new在堆区开辟内存空间,存放数据类型的数据,返回该数据的首地址,用该数据类型的指针接收。程序结束后,使用delete调用析构函数手动释放内存空间。使用数组本质是使用数组的首地址。因此,指向数组首地址的指针可以看成是数组名,也可以当做普通指针使用。
#include<iostream>
using namespace std;
#include<string>
void test02()
{
int *ptr = new int[5]; //在堆区开辟内存空间,存放int型数组,返回该数据(数组)的首地址。
//1.ptr当做数组使用
//for (int i = 0; i < 5; i++)
//{
// ptr[i] = i + 100;
//}
//for (int i = 0; i < 5; i++)
//{
// cout << ptr[i] << endl;
//}
//2.ptr当做指针使用
//*ptr = 100;
//cout << *ptr << endl;
for (int i = 0; i < 5; i++)
{
*ptr = i + 100;
ptr++;
}
for (int i = 0; i < 5; i++)
{
cout << *(ptr-1) << endl;
ptr--;
}
delete []ptr;
}
int main()
{
test02();
system("pause");
return 0;
}
函数调用
值传递
1)函数调用时,将实参值拷贝一份(调用拷贝构造函数),然后将拷贝值传给形参。函数调用过程不可以改变实参。
2)以值方式返回局部对象,在返回时,将返回值拷贝一份(调用拷贝构造函数),然后将拷贝的数据返回。
#include<iostream>
using namespace std;
#include<string>
//无返回型
//num01'=num01;a=num01;
void test03(int a)
{
a = a + 10;
cout << a << endl;
}
//返回int型
//返回时,先将返回值拷贝一份,然后将拷贝的数据返回。
int test04(int a)
{
a = a + 10;
cout << a << endl;
return a;
}
int main()
{
int num01 = 10;
//调用test函数,过程:将实参拷贝一份,然后将拷贝的数据传递给形参。
test03(num01);
int num02 = test04(num01);
system("pause");
return 0;
}
地址传递
1)函数调用时,将实参的地址传给形参。函数的调用过程可以改变实参。
#include<iostream>
using namespace std;
#include<string>
//无返回型
void test05(int *p)
{
*p = *p + 10;
}
//返回指针型
int* test06(int *p)
{
*p = *p + 100;
return p;
}
int main()
{
int num01 = 10;
//调用test函数,过程:将实参地址传递给形参。
test05(&num01);
cout << "num01的值:" << num01 << endl;
int num02 = 10;
int *ptr = test06(&num02);
cout << "num02的值:" << num02 << endl;
system("pause");
return 0;
}
引用传递
1)函数调用时,将实参的引用传给形参。可以改变实参。
2)以引用返回局部对象,在返回时,将局部对象的引用返回。注意不要返回局部对象的引用,因为局部对象存储在栈上,函数调用结束后,编译器会自动释放栈区内存。
3)引用的本质是一个指针常量,引用一旦初始化,指向就不可以发生更改。常量引用(const修饰)使指向的值也不可以更改。
#include<iostream>
using namespace std;
#include<string>
//无返回型
void test07(int &ref)
{
ref = ref + 10;
}
//返回引用型
int& test08(int &ref)
{
ref = ref + 100;
return ref;
}
//常量引用
void test09(const int &ref)
{
//ref = ref + 10;常量引用不可改变引用的值。
cout <<"打印的值:" << ref << endl;
}
int main()
{
int num01 = 10;
//调用test函数,过程:将实参引用传递给形参。
test07(num01);
cout << "num01的值:" << num01 << endl;
int num02 = 10;
int num03 = test08(num02);
cout << "num02的值:" << num03 << endl;
int num04 = 30;
test09(num04);
system("pause");
return 0;
}
总结
在函数调用时,值传递的方式传参和返回局部对象会调用拷贝构造函数将实参拷贝一份,因此使用引用传递和地址传递的效率更高。