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

目录

  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知识 继承、多态、模版,欢迎关注公众号”音视频开发之旅”,一起学习成长。

欢迎交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259