首页 > 编程语言 >【C++入门】(三)创建指针

【C++入门】(三)创建指针

时间:2022-09-23 10:47:49浏览次数:43  
标签:入门 int C++ 地址 内存 pAge 变量 指针

1. 指针是什么?

1.1 理解指针及其用途

  1. 变量 是可存储一个值的对象: 整型变量 存储一个数字; 字符变量 存储一个字母;

  2. 指针 是存储 内存地址 的变量

  3. 计算机内存是存储变量值的地方。根据约定,计算机内存被划分成按顺序编号的内存单元,每个内存单元都有地址(内存编址方案随计算机而异,不必要知道每个变量的地址对应的数字,重点是关心每个变量都有地址且编译器依据声明的变量类型给它分配了正确的内存量)

 

1.2 指针、地址和变量

int a = 5;
int* p = &a;
​
cout << "a= " << a << endl;      //变量,   a = 5
cout << "p= " << p << endl;      //指针p,  p = 000000F4DEDCFC44
cout << "*p= " << *p << endl;    //解引用,*p = 5

 

 

1.3 为何使用指针

指针常用于完成以下三项任务:

① 管理堆中数据;

② 访问类的成员数据和成员函数;

③ 按引用将变量传递给函数;

 

 

2. 如何声明和使用指针?

2.1 在指针中存储地址

  1. 每个变量都有地址,即使不知道变量的具体地址,也可以将地址存储在指针中

  2. 声明指针:

    int *pAge = nullptr;
    ​
    //注意,pAge 也是变量(指针是一种特殊的变量),用于存储对象在内存中的地址。
    //此处 pAge 存储了一个int变量的地址,初始化为 nullptr(空指针 = NULL = 0)

     

  1. 声明指针时,指定它将指向的变量类型(这告诉编译器如何处理指针指向的内存单元,指针自己本身包含了一个地址)

  2. 声明指针时,必须将其初始化(如果不知道指什么值,就指向空)

  3. 未被初始化的指针称为 野指针 ,野指针十分危险

  4. 如果将指针初始化为 nullptr,后面必须将变量的地址赋给它:

    int HowOld = 50;
    int *pAge = nullptr;
    pAge = &HowOld;
    ​
    //① 创建 int变量 HowOld,并初始化为50;
    //② 将 pAge 声明为 int*指针,并初始化为 nullptr(空指针);
    //③ 将 HowOld 的地址赋值给 pAge (取址符&)
    
    //上述代码可优化:
    ​
    int HowOld = 50;
    int *pAge = &HowOld;
    ​
    //使用 pAge 来访问 HowOld 的值,被称为 间接访问

     

  1. 间接访问 指的是访问指针存储的地址处的值,指针提供了一种间接获取值的方式

 

 

2.2 间接运算符(间接地使用指针)

  1. 间接运算符 / 解除引用运算符 *

    int HowOld = 50;
    int* pAge = &HowOld;
    int YourAge;
    YourAge = *pAge;
    //从 pAge 指向的地址处获取值,并将其赋给 YourAge
    ​
    cout << HowOld << endl;  
    cout << YourAge << endl;
    //50
    //50
     

     



  1. 注意区分:

    间接运算符 * 以两种不同的方式作用于指针,即 声明解除引用

    (1)声明指针时( int* p = &a; ), * 表示这是指针,而非其他变量

    (2)解除引用时( *p = 5; ), * 表示访问指针指向的内存单元中的值,而非地址本身

    (3)此外, * 还表示乘法运算符,编译器会根据上下文来判定

    int a = 50;
    int* p = &a;
    *p = 5;
        
    cout << p << endl;  // 等价于cout << &a << endl;
    cout << *p << endl;
    //000000392176FC74
    //5

     

 

2.3 使用指针操作数据

(改)

int myAge;            // 声明一个变量
int* pAge = NULL;     // 声明一个空指针
​
myAge = 5;         // 变量赋值5
pAge = &myAge;     // 指针 pAge 获取变量的地址
cout << "myAge: " << myAge << endl;      // myAge: 5
cout << "*pAge: " << *pAge << endl;      // *pAge: 5
​
*pAge = 7;         // 解引用 *pAge = 7(指针指向的内存单元中的值,修改为7),等价于 myAge = 7;
cout << "*pAge: " << *pAge << "\n";      // myAge: 7
cout << "myAge: " << myAge << "\n\n";    // *pAge: 7
​
myAge = 9;         // 变量赋值9
cout << "myAge: " << myAge << "\n";      // myAge: 9
cout << "*pAge: " << *pAge << "\n";      // *pAge: 9

(查)

没啥好说的,就是注意一下,指针自己本身也有相应的地址,该地址可存储在指针中(也可以赋给其他的指针)

 

 

3. 什么是堆,如何操作内存?

3.1 堆和栈

  1. 程序员通常需要处理以下5个内存区域:

    • 全局名称空间

    • 寄存器

    • 代码空间

  2. 中存储了 局部变量函数参数

    代码空间 放了 代码

    全局名称空间 存储了 全局变量

    寄存器 用于 内部管理(如跟踪栈顶和指令指针)

    余下所有的内存都分给了 ,堆有时也被称为 自由存储区

  3. ① 局部变量的局限性是不会持久化,函数返回时,局部变量将丢弃;

    ② 全局变量解决了上述问题,但代价是在整个程序中都能访问它,这导致代码容易出bug;

    而将数据放在 中可以解决上述2个问题。

  4. 堆的优点在于:在显示释放前,预留的内存始终可用。如果在函数中预留堆中的内存,在函数返回后,该内存仍可用。

  1. 以这种方式(而不是全局变量)访问内存的优点是:只有有权访问指针的函数才能访问它指向的数据。这提供了控制严密的数据接口,消除了函数意外修改数据的问题。

 

3.2 使用关键字 new

  1. 使用关键字 new 分配堆中内存,并在它后面指定要为之分配内存的对象的类型

    int *p;
    p = new int;
    ​
    //等价于: int *p = new int;
    //关键字new返回一个内存地址,必须将其赋给指针(分配内存时,注意指针不要为空)
    ​


3.3 使用关键字 delete

  1. 在使用完分配的内存区域后,必须对指针调用 delete ,将内存归还给堆

  2. 使用 new 运算符分配的内存不会自动释放,这些内存将不可用,这被称为 内存泄露 ,因为在程序结束前,内存不会归还给堆,就像内存从计算机中漏掉了

    delete p;
    ​
    //删除指针时,实际是释放了其地址存储在指针中的内存,,这被称为将指针指向的内存归还给堆
    //指针还是指针,可重新给它赋值
    //对指针调用 delete 时,将释放它指向的内存。如果再次对该指针调用 delete,就将导致程序崩溃
    ​
    p = nullptr;
    delete p;
    ​
    //删除指针时,应将其置空,再对空指针调用 delete,则是安全的
    ​


3.4 避免内存泄露

  1. 除了 new 完不释放,还有一种无意间导致内存泄露的情况:没有释放指针指向的内存就给它重新赋值。

    int *p = new int;
    *p = 72;
    ​
    delete p;  //程序中每个 new 调用都必须有对应的 delete 调用,使用完后及时将内存释放出来
    ​
    p = new int;
    *p = 82;


3.5 空指针常量

  1. 使用指针时,需要将指针初始化(未初始化的指针比较野)

    int *p = 0;
    int *p = NULL;
    ​
    //这2条语句等效,因为 NULL 是一个预处理器宏,将被转换为0
    
    
  1. 而又因为 0 既可以表示指针常量,又可表示整形常量,带来了二义性

    int *p = nullptr;
    ​
    //出于向后兼容的考虑,使用关键字 nullptr 来给指针置空
    //(nullptr 不会被隐式地转换为整数,在需要布尔值的地方,它将被转换为False) ​

     

标签:入门,int,C++,地址,内存,pAge,变量,指针
From: https://www.cnblogs.com/ZWJ-zwj/p/16721859.html

相关文章

  • 【办公自动化】正则表达式的入门及提高学习网站
    这个网站有入门101课程,带中文的。强烈推荐!https://regexlearn.com/zh-cn/learn/regex101记录一下学习心得:1、abcd*和abcd+......
  • 【C++入门】(四)开发高级指针
    1.如何在堆中创建对象?1.1在堆中创建对象定义了类型Cat后,便可声明一个指向这种对象的指针,并在堆中实例化一个Cat对象,就像在栈中实例化一样Cat*pCat=newCat;......
  • 【C++入门】(一)创建基本类
    1.类型是是什么?类型是一个包含数据和功能的对象 2.什么是类和对象?C++类是一个模板,用于创建对象。类是一系列捆绑在一起的变量和函数,变量构成了类的数据,......
  • C入门第一笔
    C语言源代码(由高级语言编写C++、Java等)—>通过C语言编译程序编译—>二级制机器指令(0和1)源程序......
  • C++ "链链"不忘@必有回响之双向链表
    C++"链链"不忘@必有回响之双向链表1.前言写过一篇与单链表相关的博文(https://blog.51cto.com/gkcode/5681771),实际应用中,双向循环链表的功能更强大。单链表中,查询一个......
  • cesium 入门指南
    最近拿到了几份offer,经过这次找工作发现自己最近脱节挺严重,为了后续的职业发展,决定开始书写博客记录自己的努力。cesium属于跨平台、跨浏览器的展现三维地球、地图的Java......
  • 「浙江理工大学ACM入队200题系列」问题 A: 零基础学C/C++34—— 3个数比较大小(冒泡排
    深夜写的,代码都还没来得及跑一便,可能有错误,欢迎指出,后续会检验一遍并修改错误.本题是浙江理工大学ACM入队200题第四套中的A题,同时给出了冒泡排序和选择排序算法......
  • 从汇编看C++函数返回对象
    同样的代码,在msvc和gcc里面实现不同。structTest{inta;intb;intc;intd;~Test(){std::cout<<"end"<<std::endl;}};TestgetTest(){Testsa;sa.a=1......
  • NLP新手入门指南|北大-TANGENT
    开源的学习资源:《NLP新手入门指南》,项目作者为北京大学TANGENT实验室成员。该指南主要提供了NLP学习入门引导、常见任务的开发实现、各大技术教程与文献的相关推荐等......
  • C++:储存持续性、作用域及链接性
      C++11的存储类别会影响信息在文件间的共享,一共有四种方案来保存数据,也就是变量的保存时间,而作用域决定变量的保存范围。持续时间自动存储连续性:函数内部定义中声明......