美文网首页C++
音视频开发之旅(20) 指针、内存模型、引用

音视频开发之旅(20) 指针、内存模型、引用

作者: yabin小站 | 来源:发表于2021-01-02 12:53 被阅读0次

目录

  1. 指针
  2. 内存模型和四区使用
  3. 引用
  4. 资料
  5. 收获

一、指针

1.1 什么是指针?

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

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

其中指针运算和地址运算互为逆运算。
即&用于取地址;*用于指针指向的具体内容

1.2 指针常量、常量指针

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

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

下面用示例说明:

#include<stdio.h>
#include<iostream>
using namespace std;

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

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

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

    cout << *p<<endl;

   //常量指针:本质上是一个指针,指针指向的内容不可以改变, 但指针的指向(地址)可以变化

    const int * p2 = &a;
    p2 = &b;

    // *p2 = 2; //错误 常量指针 只能修改地址指向,但不能修改指向内容的值

    cout << *p2 <<endl;

    return 0;
}

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

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

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

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

 int *p;
 cout<< p<<endl;
 cout<<*p<<endl;  //Exception has occurred. EXC_BAD_ACCESS (code=1, address=0x0)

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

  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<<endl;
    cout<< *(p+1)<<endl;

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

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

    char (*p)[3] = tmp;

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

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

1.5 指针函数与函数指针

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

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

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

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

示例如下:

#include<stdio.h>
#include<iostream>
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<<p<<endl;
    cout<<*p<<endl;
    return 0;
}

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

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

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

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

示例如下:

#include<stdio.h>
#include<iostream>
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<<fun(a,b)<<endl;

    fun = sub;
    cout<<fun(a,b)<<endl;

    return 0;
}

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

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 <<endl;

    ref = 100;
    cout <<a<<endl;
}

**引用作为函数参数**
//值传递、地址传递、引用传递 形参数修饰实参数

void swap(int &a,int &b){
    int temp = a;
    a=b;
    b=temp;
}


int main()
{
    int a = 1;
    int b = 2;
    swap(a,b);
    cout << a <<endl;
    cout << b <<endl;
}

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

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

int a=1;

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

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

资料

[什么是野指针和内存泄漏?如何避免野指针] : https://blog.csdn.net/qq_35212671/article/details/51920851
[C++基础教程]: http://c.biancheng.net/cplus/

收获

  1. 学习回顾指针相关的概念和使用
  2. 熟悉内存模型
  3. 动态分配内存以及智能指针的使用
  4. 引用的使用

感谢你的阅读

下一篇我们继续学习实践cpp知识 继承、多态、模版,欢迎关注公众号”音视频开发之旅”,一起学习成长。

欢迎交流

相关文章

  • 音视频开发之旅(20) 指针、内存模型、引用

    目录 指针 内存模型和四区使用 引用 资料 收获 一、指针 1.1 什么是指针? 指针本质上是地址,用于指向具体的...

  • C++ 指针与引用

    指针和引用的区别? 指针是实体,它指向⼀块内存,它的内容是所指内存的地址;引用是某块内存的别名 引用只能在定义时被...

  • 链表代码注意事项

    1、理解指针或引用的含义 比如C语言是指针,就是相当于JAVA的引用 2、警惕指针丢失和内存泄漏 C 语言,内存管...

  • iOS ,内存分布、内存管理 、isa 指针,散列表(引用计数表

    iOS ,内存分布、内存管理 、isa 指针,散列表(引用计数表,弱引用表) 内存管理方案 1.taggedPoi...

  • 多级指针

    多级指针注意引用即可,主要的还是多级指针和动态内存之间的跨函数使用内存

  • Rust for cpp devs - 智能指针

    与 cpp 类似,Rust 也有智能指针。Rust 中的智能指针与引用最大的不同是,智能指针 own 内存,而引用...

  • GoAdvance

    指针 指针就是地址,指针变量就是存储地址的变量 *p : 解引用,间接引用 栈帧:用来给函数运行提供内存空间,取内...

  • 内存管理解析

    目录 1.内存区域解析2.什么是引用计数(retainCount)3.什么是指针和地址4.内存泄漏、野指针、空指针...

  • 指针与引用区别

    引用与指针的区别 (1)引用是给另外一个变量取别名,所以不会分配内存空间。 指针是一个实体,需要分配内存空间。 (...

  • 面经1

    语言基础C++ 1、指针和引用的区别?相同点:都是地址的概念;指针指向一块内存,它的内容是所指内存的地址;引用是某...

网友评论

    本文标题:音视频开发之旅(20) 指针、内存模型、引用

    本文链接:https://www.haomeiwen.com/subject/uqjeoktx.html