• Android NDK篇-C++之 强制转换与智能指针


    1.c++ 强制转换之 const_cast (cosnt 常量相关的)
    #include 
    
    using namespace std;
    
    class Person {
    public:
        string name = "小舞";
    };
    
    int main() {
        const Person * p1 = new Person();
        // p1->name = "Derry"; // 报错:常量指针,不写修改值
    
        Person * p2 = const_cast(p1); // 转成 非常量指针
        p2->name = "唐三";
    
        cout << p1->name.c_str() << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    通过const_cast 将常量对象,强转为非常量对象,一达到修改常量指针的值得目的。

    const相关的强转都可以使用这个来强转

    2.c++ 强制转换static_cast (指针相关的)
    class FuClass {
    public:
        void show() {
            cout << "fu show" << endl;
        }
    };
    
    class ZiClass  : public FuClass {
    public:
        void show() {
            cout << "zi show" << endl;
        }
    };
    
    int main() {
    
        FuClass * fuClass = new FuClass;
        // fuClass->show();
        ZiClass * ziClass = static_cast(fuClass);
        ziClass->show();
    
        delete fuClass; 
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • static_cast(编译期) 看左边 ZiClass * 左边是什么类型就调用什么类型的方法
    • 回收规则:一定是谁new了,我就delete谁
    3.c++强制转换 dynamic_cast 动态转换
    #include 
    using namespace std;
    
    class FuClass {
    public:
        // 动态转换必须让父类成为虚函数
        virtual void show() {
            cout << "fu show" << endl;
        }
    };
    
    class ZiClass  : public FuClass {
    public:
        void show() {
            cout << "zi show" << endl;
        }
    };
    
    int main() {
    
        // FuClass * fuClass = new FuClass(); // 失败
        FuClass * fuClass = new ZiClass; //子类 成功
        ZiClass * ziClass = dynamic_cast(fuClass);
    
        if (ziClass) { // ziClass != null
            cout << "转换成功 " ;
            ziClass->show();
        } else {
            cout << "转换失败" << endl ;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 动态类型转换的时候,在运行期 由于fuClass 是new 父类的,就不能转换子类(new 的是谁就能转谁)
    • 动态转换是有返回值, null 转换失败
    4.c++ 强制类型转换 reinterpret_cast
    #include 
    
    using namespace std;
    
    class Handler {
    public:
        void show() {
            cout << "handler" << endl;
        }
    };
    
    int main() {
        Handler * handler = new Handler();
        long handlerValue = reinterpret_cast(handler); // 把对象变成数值
    
        // 通过数值 变成对象
        Handler * handler2 = reinterpret_cast(handlerValue);
        handler2->show();
    
        printf("handler:%p\n", handler);
        printf("handler2:%p\n", handler2);
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • reinterpret_cast 用于引用句柄,在NDK以及Android底层广泛应用
    • 主要是可以将对象转换long,然后保存long类型,等到使用的时候将long类型再转回对象
    5.c++智能指针之shared_ptr

    智能指针作用是为了自动释放堆对象内存,真实项目中由于代码量很大,可能会忘记对堆内存的释放,为了解决这个问题,引入的智能指针。

    #include 
    #include 
    
    using namespace std;
    
    
    class Person2; // 先声明 Person2 让我们的Person1 直接找到
    
    
    class Person1 {
    public:
        shared_ptr person2; // Person2智能指针  shared_ptr 引用计数+1
        ~Person1() {
            cout << "Person1 析构函数" << endl;
        }
    };
    
    class Person2 {
    public:
        shared_ptr person1;  // Person1智能指针  shared_ptr 引用计数+1
        ~Person2() {
            cout << "Person2 析构函数" << endl;
        }
    };
    
    
    int main(){
    
        Person1 * person1 = new Person1(); // 堆区开辟
        Person2 * person2 = new Person2(); // 堆区开辟
    
        shared_ptr sharedPtr1(person1); // +1 = 1
        shared_ptr sharedPtr2(person2); // +1 = 1
    
        cout << "前 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
        cout << "前 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
    
    
    //    // 给Person2智能指针赋值   循环依赖 智能指针就失去了自动释放内存的功能了
    //    person1->person2 = sharedPtr2;
    //    // 给Person1智能指针赋值
    //    person2->person1 = sharedPtr1;
    //
    //
    //    cout << "后 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
    //    cout << "后 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 虽然使用shared_ptr能够非常方便的为我们自动释放对象,但是还是会出现一些问题。最典型的就是循环引用问题。
    6.c++智能指针之weak_ptr

    weak_ptr是为配合shared_ptr而引入的一种智能指针。主要用于观测资源的引用情况。它的构造和析构不会引起引用记数的增加或减少。没有重载*和->但可以使用lock获得一个可用的shared_ptr对象。

    配合shared_ptr解决循环引用问题

    #include 
    #include  // 智能指针的头文件引入
    using namespace std;
    
    class Person2; // 先声明 Person2 让我们的Person1 直接找到
    
    class Person1 {
    public:
        weak_ptr person2; // Person2智能指针  没有引用计数 无法+1
        ~Person1() {
            cout << "Person1 析构函数" << endl;
        }
    };
    
    class Person2 {
    public:
        weak_ptr person1;  // Person1智能指针  没有引用计数 无法+1
        ~Person2() {
            cout << "Person2 析构函数" << endl;
        }
    };
    
    
    int main() {
        Person1 * person1 = new Person1(); // 堆区开辟
        Person2 * person2 = new Person2(); // 堆区开辟
    
        shared_ptr sharedPtr1(person1); // +1 = 1
        shared_ptr sharedPtr2(person2); // +1 = 1
    
        cout << "前 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
        cout << "前 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
    
        // 给Person2智能指针赋值
        person1->person2 = sharedPtr2;
        // 给Person1智能指针赋值
        person2->person1 = sharedPtr1;
    
        cout << "后 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
        cout << "后 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
    
        return 0;
    } // 减1 = 0 释放对象
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    7.c++智能指针unique_ptr

    实现独占式引用,保证同一时间只有一个智能指针指向内部对象。

    #include 
    #include  // 智能指针的头文件引入
    
    using namespace std;
    
    class Person {
    public:
        ~Person(){
            cout<<"析构函数"< uniquePtr1(person1);
    
        // 严格禁止
    //     std::unique_ptr uniquePtr2 = uniquePtr1;  unique不允许,因为是独占的
    
        // shared_ptr 是可以的,会造成隐患问题
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    8.自定义实现类似shared_ptr智能指针
    #include 
    using namespace std;
    
    template
    
    class Ptr{
    
    
    private:
        T * object;         // 用于智能指针指向管理的对象  Person Student
        int * count;        //引用计数
    
    public:
        Ptr(){
            count=new int(1);  // new 的对象 必须 *指针  
            object=0;  // 因为你没有给他对象 智能赋值为0
        }
    
        Ptr(T *t):object(t){
    //        只有你存入对象,那么引用计数为1,这个是很合理的
            count=new int(1);
        }
    
    
        ~Ptr(){
            if (--(*count)==0){
                if (object){
                    delete object;
                }
    
                delete count;
                object=0;
                count=0;
            }
        }
    
        //拷贝构造函数
        Ptr(const Ptr & p){
            cout << "拷贝构造函数" << endl;
            ++(*p.count);
            object = p.object;
            count = p.count; // 最终是不是 p.count==2 给 count==2
        }
    
        // 自定义 =号运算符重载
        Ptr & operator = (const Ptr & p){
            cout << "=号运算符重载" << endl;
            ++(*p.count);
    
            if (--(*count) == 0) {
                if (object) {
                    delete object;
                }
                delete count;
            }
    
            object = p.object;
            count = p.count;
            return *this; // 运算符重载的返回
        }
    
        // 返回引用计数的数值
        int use_count() {
            return *this->count;
        }
    
    };
    
    int main(){
        //自定义智能指针的应用
        Student *student1 = new Student();
        Student *student2 = new Student();
    
        Ptr sharedPtr1(student1);
        Ptr sharedPtr2(student2);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
  • 相关阅读:
    ffmpeg知识点整理
    2023/11/15JAVA学习(线程池,Executors,网络编程,InetAddress,UDP,TCP,DatagramSocket)
    论文精度 —— 2017 ACM《Globally and Locally Consistent Image Completion》
    二叉树进阶
    【MySQL】select语句——group by子句和having子句的使用
    Python 教程之使用 Python 和 Graphviz 动画正则表达式 窥探正则表达式引擎的内部
    把key-value键值对的数据转换成xml格式,并根据key来匹配元素
    【算法|前缀和系列No.2】牛客网 DP35 【模板】二维前缀和
    JavaScript混淆工具大比拼:JScrambler和JShaman哪个更胜一筹?
    elasticsearch-7.9.3 单节点启动配置
  • 原文地址:https://blog.csdn.net/u014078003/article/details/126456927