首页 > 编程语言 >【C++入门】(四)开发高级指针

【C++入门】(四)开发高级指针

时间:2022-09-23 10:44:53浏览次数:41  
标签:const 入门 指向 int C++ 对象 SimpleCat 指针

1. 如何在堆中创建对象?

1.1 在堆中创建对象

  1. 定义了类型 Cat 后,便可声明一个指向这种对象的指针,并在堆中实例化一个 Cat 对象,就像在栈中实例化一样

    Cat *pCat = new Cat;
    ​
    // 这将调用默认构造函数 —— 不接受任何参数的构造函数
    // 每当在堆或栈中创建对象时,都将调用构造函数

     

  1. 为什么要在堆中声明对象?

    函数返回后,在堆中声明的对象依然存在。这种对象还是动态的;此外,在堆中声明的对象可用来创建复杂的数据结构

1.2 删除对象

  1. 对指向堆中对象的指针调用 delete 时,将调用对象的析构函数,然后释放内存。这让类有机会执行清理工作,就像销毁栈中的对象一样

    delete pCat;
    #include <iostream>
    using namespace std;
    ​
    class SimpleCat
    {
    public:
        SimpleCat();
        ~SimpleCat();
    private:
        int itsAge;
    };
    ​
    SimpleCat::SimpleCat()
    {
        cout << "调用构造函数SimpleCat" << endl;
        itsAge = 1;
    }
    ​
    SimpleCat::~SimpleCat()
    {
        cout << "调用析构函数~SimpleCat" << endl;
    }
    ​
    int main()
    {
        cout << "1. 创建一个名为 Frisky 的 SimpleCat类型对象" << endl;
        SimpleCat Frisky;
    ​
        cout << "2. 在堆中new一个SimpleCat对象,并让指针pRags指向它" << endl;
        SimpleCat* pRags = new SimpleCat;
    ​
        cout << "3. 删除指针 pRags" << endl;
        delete pRags;
    ​
        cout << "4. 函数结束时,Frisky不再在作用域内" << endl;
        return 0;
    }
    ​
    //1. 创建一个名为 Frisky 的 SimpleCat类型对象
    //调用构造函数SimpleCat
    //2. 在堆中new一个SimpleCat对象,并让指针pRags指向它
    //调用构造函数SimpleCat
    //3. 删除指针 pRags
    //调用析构函数~SimpleCat
    //4. 函数结束时,Frisky不再在作用域内
    //调用析构函数~SimpleCat

  1. 如果程序员没有显性地执行 delete 命令,对象将在不再在作用域时被删除(调用析构函数)

    如果对象是在 main() 中创建的,且程序员没有显性地删除它,则在 main() 结束后,将调用析构函数

 

2. 如何高效地使用指针?

2.1 使用指针访问数据成员

  1. 对于在栈中创建的 Cat 对象,使用句点运算符 . 来访问其成员数据和成员函数

    (*pRags).GetAge();
    ​
    //要访问堆中 Cat 对象,必须对指针解除引用,并对指针指向的对象使用句点运算符
    // (*pRags) 用括号括起来,以确保对pRags解引用后再访问GetAge()
  2. C++还提供一种简洁的间接访问运算符 -> 指向运算符

    pRags->GetAge();
    
    

2.2 堆中的数据成员

  1. 类可能有一个或多个数据成员为指针,并指向堆中的对象。

    可在构造函数或成员函数中分配内存,并在析构函数中释放内存

    #include <iostream>
    ​
    class SimpleCat
    {
    public:
        SimpleCat();
        ~SimpleCat();
    ​
    private:
        int* itsAge;
        int* itsWeight;
    };
    ​
    SimpleCat::SimpleCat()
    {
    ​
    }
    ​
    SimpleCat::~SimpleCat()  //2. 需要自己写析构函数,否则会造成内存泄露
    {
        delete itsAge;
        delete itsWeight;
    }
    ​
    int main()
    {
        SimpleCat* Frisky = new SimpleCat;
    ​
        delete Frisky;  //1. delete只删除指向堆内存的指针,而不会删除堆中的内容
        return 0;
    }
     

 

2.3 this指针

  1. 每个类成员函数都有一个隐藏的参数 —— this指针 ,它指向用于调用函数的对象

    (通常只是调用函数并设置成员变量的情况下,并不需要this指针,偶尔需要访问对象本身时,this指针将很有用)

    class Rectangle
    {
    public:
        Rectangle();
        ~Rectangle();
      //显示的使用了 this指针 来访问 Rectangle对象 的成员变量,没啥软用
        void SetLength(int length) { this->Length = length; }
        int GetLength() const { return this->Length; }
    ​
    private:
        int Length;
    };
     //不用管 this指针的创建和删除,编译器会负责善后
    
    

2.4 悬摆指针

  1. 悬摆指针 / 野指针 / 迷失指针 是bug之源(之一)

  2. 对指针调用 delete(从而释放它指向的内存)后,如果没有重新赋值就使用,将导致悬摆指针

  3. 对指针调用 delete 后,千万不要使用它。该指针仍指向原来的内存区域(但编译器可能在这里存储了其他数据),使用该指针可能导致程序崩溃。出于安全考虑,删除指针后,应将其设为nullptr

 

2.5 const指针和 const成员函数

  1. const int *p1; 指针指向的对象是常量

    int * const p2; 指针本身是常量

    const int *p1;
    ​
    // p1 是指向整型常量的指针,使用该指针 不能修改它指向的值
    // 不能写 *p1 = 5; 这样的代码
    int * const p2;
    ​
    // p2 是指向整型的常量指针,使用该指针 可修改它指向的整型变量,但不能指向其他变量,不能给常量指针重新赋值
    // 不能写 *p2 = &x; 这样的代码
    const int * const p3;
    ​
    // p3 是指向整型常量的常量指针,使用该指针 不能修改它指向的值,也不能让它指向其他变量

     

 

  1. const 常量成员函数

    class Rectangle
    {
    public:
        //void SetLength(int length) const { itsLength = length; }  //报错,常量成员函数不可修改
        int GetLength() const { return itsLength; }
    ​
    private:
        int itsLength;
        int itsWidth;
    };

     

  1. 如果声明了一个指向常量对象的指针,那么使用该指针只能调用常量函数

    class Rectangle
    {
    public:
        int func1() const { return itsLength; }  //const常量函数
        int func2()       { return itsLength; }
    ​
    private:
        int itsLength = 66;
    };
    ​
    int main()
    {
        //如果声明了一个指向常量对象的指针,那么使用该指针只能调用常量函数
        const Rectangle* p2 = new Rectangle;
    ​
        cout << "指向常量对象的指针p2,只能调用常量函数"<< p2->func1() << endl;
        //cout << "指向常量对象的指针p2,只能调用常量函数"<< p2->func2() << endl;
        //对象含有与成员 函数 "Rectangle::func2" 不兼容的类型限定符   
    ​
        return 0;
    }​
    
    
  2. 将对象声明为常量时,实际上是将 this 声明为指向常量对象的指针。

    常量 this指针 只能用于调用常量成员函数

 

 

3. 使用指针时如何避免内存问题?

  1. 指针定义后要初始化,没有指向时指向NULL;

  2. 指针赋值时一定要保证类型匹配

    由于指针类型确定指针所指向对象的类型,因此初始化或赋值时必须保证类型匹配;

  3. 两个指针最好不要指向同一块内存,一个指针的释放会导致另一个指针成为悬垂指针,造成不堪设想的后果;

  4. 释放指针内存后要将该指针置空;

  5. 指针分配成功后才可以使用,要走注意分配后的大小,不要越界。

 

 

4.总结

  1. 指针可指向整型等简单数据类型,也可以指向对象

  2. 可在堆中创建对象,并将其删除(可声明指向类的对象的指针,并在堆中实例化对象)

  3. 类的数据成员可以是指向堆中对象的指针

  4. 可在类的构造函数或其他函数中分配内存,并在析构函数中将其释放

标签:const,入门,指向,int,C++,对象,SimpleCat,指针
From: https://www.cnblogs.com/ZWJ-zwj/p/16721883.html

相关文章

  • 【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的存储类别会影响信息在文件间的共享,一共有四种方案来保存数据,也就是变量的保存时间,而作用域决定变量的保存范围。持续时间自动存储连续性:函数内部定义中声明......
  • Azure CTO 呼吁不要使用 C/C++ 创建新项目,C++ 之父回应:你们这些高管就爱喜新厌旧
    AzureCTO呼吁不要使用C/C++创建新项目,C++之父回应:你们这些高管就爱喜新厌旧投递人 itwriter 发布于2022-09-2120:44 评论(0) 有661人阅读 原文链接 [收藏] ......
  • AOP入门案例
     导入坐标   制作共性功能  定义切入点  绑定切入点和通知关系      ------------------------------------        ......