C++中的内存分配、引用、函数知识补充


C++中的内存

内存分区模型

  • C++在执行程序时,将内存大致分成四个区域
    代码区:存放函数体的二进制代码,由操作系统进行管理
    全局区:存放全局变量和静态局部变量以及常量
    栈区:由编译器自动分配和释放,存放函数的参数值,局部变量等
    堆区:由程序员分配和释放,若程序员不释放,则程序结束时由操作系统释放
  • 内存四区的意义:
    ○ 不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程

程序运行前

  • 在程序编译后,生成了.exe 结尾的可执行程序,未执行该程序前分为两个区域
  • 代码区:
    ○ 存放CPU执行的机器命令
    ○ 代码区是共享的,共享的目的是对于频繁执行的程序,只需要在内存中有一份代码即可;
    ○ 代码区是只读的,是只读的原因是防止程序意外地修改了它的指令
  • 全局区:
    全局变量静态变量存放在此
    ○ 全局区还包含了常量区字符串常量其它常量也存放于此
    该区域的数据在程序结束后由操作系统释放
  • 常量区中:
    ○ 字符串常量
    ○ const 修饰的全局常量

程序运行后

  • 栈区:
    ○ 由编译器自动分配释放,存放函数的参数值,局部变量等
    ○ 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
  • 堆区:
    ○ 由程序员分配和释放,若程序员不释放,则程序结束时由操作系统释放
    ○ 在C++中用 new 开辟内存空间
//new返回的是地址,所以用指针接收
int * p = new int (1);

new 运算符

● 在C++中用new在堆上开辟空间;
● 用 delete 释放堆上的空间;

//new运算符的使用
#include <iostream>
using namespace std;
int main() {
    /* new 返回该数据类型的指针
     * 用相应类型的指针接收
     */
    int * p = new int(1);
    cout<<"堆区开辟数据:*p= "<<*p<<endl;
    //用delete释放堆上的空间
    delete p;
    /* 开辟数组
     */
    int * arr = new int[3];
    for(int i = 0;i<3;i++)
    {
        arr[i] = i+1;
        cout<<"arr["<<i<<"]="<<arr[i]<<endl;
    }
    //释放堆上的数组
    delete []arr;
    return 0;
}
/*
堆区开辟数据:*p= 1
arr[0]=1
arr[1]=2
arr[2]=3
*/

引用

● 作用:给变量起别名
● 语法:&别名 = 变量;

//
// Created by NJUST'er'wang's on 2022/1/13.
//引用
#include <iostream>

using namespace std;

int main() {
    //引用的基本语法
    int a = 10;
    int &b = a;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout<<"----------"<<endl;
    b = 100;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    return 0;
}
/*
a = 10
b = 10
----------
a = 100
b = 100
*/
  • 注意事项:
    ○ 引用必须初始化:
int &b;			//❌
int &b = b1;	//√

○ 初始化后不能更改

int a = 1;
int &b = a;
int c = 2;
b = c;		//这儿不是更改别名,而是赋值
/*
a = 2	b = 2	c = 2
*/

引用做函数的参数

○ 作用:函数传参时,可以利用引用的技术让形参修饰实参
○ 优点:可以简化指针修改实参

//
// Created by NJUST'er'wang's on 2022/1/13.
//引用和函数
#include <iostream>
using namespace std;
void swap01(int a,int b){
    int t =a;
    a = b;
    b = t;
}
void swap02(int * a,int * b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void swap03(int &m,int &n){
    int temp = m;
    m = n;
    n = temp;
}

int main()
{
    int a = 1,b =2;
    cout<<"初始值:"<<' ';
    cout<<"a= "<<a<<' '<<"b= "<<b<<endl;

    //值传递形参不修饰实参
    cout<<"值传递:"<<' ';
    swap01(a,b);
    cout<<"a= "<<a<<' '<<"b= "<<b<<endl;

    //地址传递形参修饰实参
    cout<<"地址传递:"<<' ';
    swap02(&a,&b);
    cout<<"a= "<<a<<' '<<"b= "<<b<<endl;

    swap02(&a,&b);//将值更正
    //引用形参修饰实参
    cout<<"引用:"<<' ';
    swap03(a,b);
    cout<<"a= "<<a<<' '<<"b= "<<b<<endl;

    return 0;
}
/*
初始值: a= 1 b= 2
值传递: a= 1 b= 2
地址传递: a= 2 b= 1
引用: a= 2 b= 1
*/

引用做函数返回值

//
// Created by NJUST'er'wang's on 2022/1/13.
//引用做函数返回值
#include <iostream>

using namespace std;

int &fun() {
    static int a = 8848;
    return a;
}

int main() {
    int &ret = fun();
    cout << "ret= " << ret<<endl;
    cout<<"------------"<<endl;
    fun() = 10086;
    cout << "ret= " << ret;
    return 0;
}
/*
ret= 8848
------------
ret= 10086
*/

引用的本质

○ 在C++内部实现是一个指针常量

/*
指针常量:指针的指向不能改变,内容可改
*/
int a = 1;
int &b = a;	//内部:int * const b = a;

int c = 2;
b = c;		//内部:*b = c;

○ 结论:C++推荐使用引用,本质上是指针,不过指针的操作都由编译器完成


常量引用

○ 使用场景:用来修饰形参,防止误操作

void fun(const int &b) //安全,防止数据被修改
{
    cout<<"b = "<<b;
}
int main()
{
    int a = 1;
    fun(a);
    return 0;
}

函数

函数的默认参数

//
// Created by NJUST'er'wang's on 2022/1/13.
//函数的默认参数
#include <iostream>

using namespace std;

int func(int a, int b = 2, int c = 3) {
    return a + b + c;
}

int main() {
    cout << "sum = " << func(1);
    return 0;
}

/*
sum = 6
*/

○ 从左往右的第一个有默认参数的形参,其右边的所有形参都必须有默认值;
○ 函数声明时有默认参数,则实现的时候不能有默认参数

  • 函数的占位参数
    ○ 语法:返回值类型 函数名(数据类型)
    ○ 默认占位参数:返回值类型 函数名(数据类型 = value)
void fun(int ){

}

函数重载

○ 作用:函数名可以相同,提高重复性
○ 条件:
■ 同一个作用域下
■ 函数名称相同
■ 函数 参数 类型不同 或者 个数不同 或者 顺序不同
■ 注意:函数的返回值不可以作为函数重载的条件
○ 注意事项:
■ 引用作为重载的条件
■ 函数重载碰到默认参数

//
// Created by NJUST'er'wang's on 2022/1/13.
//引用作为重载
#include <iostream>

using namespace std;

void fun(int &a) {
    cout << "fun with int" << endl;
}

void fun(const int &a) {
    cout << "fun with const int" << endl;
}

int main() {
    int a = 10;
    fun(a);		//a 是一个变量,可读可写,故调用前者
    fun(10);	//10是常量,只可读
    return 0;
}
/*
fun with int
fun with const int

*/
#include <iostream>

using namespace std;

void fun(int &a = 10) {			//不合法
    cout << "fun with int" << endl;
}

void fun(const int &a = 10) {	//合法
    cout << "fun with const int" << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拜见老天師

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值