音视频开发(十八):指针、内存模型、引用

音视频开发(十八):指针、内存模型、引用,第1张

目录
  1. 指针

  2. 内存模型和四区使用


一、指针 1.1 什么是指针?

指针本质上是地址,用于指向具体的内容
表达方式:数据类型 *名称

eg:
int a=1;
int *p = &a; //指针p指向a的地址
count << a<< endl;
count << *p <

其中指针运算和地址运算互为逆运算。



即&用于取地址;*用于指针指向的具体内容

1.2 指针常量、常量指针

指针常量:指针类型的常量, int *const p = &a;
本质上是一个常量, 指针指向的内容值可以修改,但是指针的指向(地址)不可以修改。


常量指针:指向常量的指针, const修饰符 const int *p1= &a;
本质上是一个指针,指针指向的内容值不可以修改,但指针的指向(地址)可以修改

下面用示例说明:

#include
#include
using namespace std;

int main()
{
    int a = 1;
    int b = 2;

    //指针常量:本质上是一个常量,指向的内容可以修改,但是指针的指向(地址)不可以改变
    int * const p =&a;
    *p =10;

    // p = &b; //错误 指针常量只能修改指向内容的值,但是不能修改地址指向

    cout << *p<
1.3 空指针与野指针以及void*类型的指针

空指针 ,一般用于指针的无指向时的初始化。


指向地址为0的地址。


int *p = NULL;
或者
int *p =0;

运行时对空指针取值会报错,因为没有访问权限。


示例如下

 int *p;
 cout<< p<

野指针 :指向了 内存被释放的内存 或者 指向了没有访问权限的内存地址的指针
野指针的原因以及如何避免

  1. 指针没有被初始化,有可能不会自动置为NULL指针而是是随机的 —》保险起见,指针初始化是赋值为具体的值或者NULL;

  2. malloc分配内存的指针,被free或者delete后,没有置为NULL,继续使用

  3. 指针的 *** 作超过了变量的作用域

(void*)类型的指针
可以指任何类型的指针但不能直接用void指针进行 *** 作,需要先转为对应类型。


相当于java中的Object

1.4 数组指针 与指针数组

数组指针:是一个指针,这个指针指向的是一个指向数组,后者说是指针的首地址。


    char tmp[2] = {'a','b'};
    char *p = tmp;
    //char *p =&tmp[0];

    cout<<*p<

指针数组:本质上是一个数组,数组中的每一个变量都是指针类型。


    char tmp[2][3] = {
        {'a','b','c'},
         {'d','e','f'},
        };

    char (*p)[3] = tmp;

    cout<< *(*(p+1)+2)<

二维数组与指针数组
二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。


而指针数组的内存分布上可能是不连续的

1.5 指针函数与函数指针

指针函数:本质上是一个函数,只是他的返回值为指针类型。



函数指针:本质上是一个指针,指向函数的指针

指针函数,即指针类型的函数,函数的返回类型是指针

格式如下
类型说明符 * 函数名(参数)

eg:
int *fun(int a,int b)

示例如下:

#include
#include
using namespace std;

int *addAddr(int a,int b){
    static int c= a+b; //注意:不要将非静态局部地址用作函数的放回值,容易出现野指针。


return &c; } int main() { int a = 1; int b = 2; int *p = addAddr(1,2); cout<

注意:不要将非静态局部地址用作函数的返回值,容易出现野指针。


指向函数的指针:指向的是程序代码存储区,指向函数代码的首地址

形式:存储类型 数据类型 (*函数指针名称)();

eg
int (*f) (int x);//声明一个函数指针
f = func; //将func函数的首地址复制给指针f

示例如下:

#include
#include
using namespace std;

int add(int a,int b){
     int c= a+b;
    return c;
}

int sub(int a,int b){
     int c= a-b;
    return c;
}

//函数指针 fun
int (*fun)(int a,int b);

int main()
{
    int a = 1;
    int b = 2;
    
    fun = add;
    cout<

函数指针作为函数的参数:地址传递(引用传递)区别于值传递
典型用法:实现函数的回调

1.6 对象指针
类名 *对象

对象指针名->成员名  

eg: Object *ptr;

ptr->getx()相当于(*ptr).getx();

二、内存分类模型、动态内存分配 2.1 内存分区模型

程序运行之前分配的内存区域:全局区和代码区
全局区:全局变量、静态变量、常量(字符串常量、const修饰的全局变量):程序结束后由 *** 作系统自动释放
代码区:存放函数体的二进制机器指令,代码区只读的且是共享的

程序运行之后分配的内存区域:栈区、堆区
栈区:编译器自动分配,存放一些局部变量、形参,会自动回收。


由编译器管理开辟和释放,不要返回局部变量的地址。


堆区:动态内存分配,程序员主动申请和释放,通过 malloc free new delete

int a = new int(1);
delete a;

int a[] = new int[10];
delete a[];

动态分配的多维数组
int (*fp)[3] = new int[2][3];
delete fp[];
2.3 智能指针

三、 引用

引用的本质是给变量起别名,指向的是同一块内存,修改别名指向的值,原名指向的值也一样修改。



语法:数据类型 &别名 = 原名

引用必须要初始化,引用初始化后就不能再改为别的变量的引用(别名)。



示例代码如下:

int main()
{
    int a = 1;

    int &ref = a;
    cout << ref < 

引用作为函数的返回值
不要返回局部变量的引用
函数的调用可以作为左值

引用的本质:在cpp内部的实现是指针常量(指针的指向不可以修改,指针指向的内容值可以修改)

int a=1;

int& ref =a 
—>
int* const ref = &a;

常量引用
用来修改时形参,防止误 *** 作

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/579118.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)