• 深度探索c++对象模型 3.6指向 data members的指针


    知识总结

    与书本所说不同,现代c++和其编译器在一段时间的发展后,本书3.6节的任何内容基本都不可以认为是对的了.
    下面提到的几点都在实验代码有印证

    指向data member的指针

    1. 没有指向任何datamember的指针
      对于没有指向任何datamember的指针,现在只能赋值NULL,nullptr,或者同类型的指针.(在赋值NULL或nullptr时,指针的值为全1)
    2. 个人猜测是完善了类型系统,导致现在已经不需要去给成员变量的指针偏移1来区分没有指向任何data member的指针和指向第一个元素的指针了. 另外说一句,咱c++别的地方也没有去加偏移来区分类似的东西啊,这里早年的处理就感觉很不美.

    多继承情况下的data member pointer使用问题

    • 现在子类指针在指向<父类class data member pointer的指向>时,总会调用正确的值.编译器会自己处理类型不同时的偏移问题.

    指向members的指针的效率问题

    在现代编译器下,使用

    1. 类指针+指向data members的指针
    2. 直接存取
    3. 指向已经绑定的member

    在优化开启时这三种时的效率已经相差无几,2,3几乎完全一样,在多重虚继承时,1可能有一些效率牺牲.但是在笔者的简单测试里也是一样的了.

    实验环境

    linux下
    gcc 11.2.0+clang 14
    c++20(c++2a)

    测试代码

    #include 
    #include 
    #include 
    using namespace std;  // bad
    class Point3d
    {
    public:
        static Point3d origin;
        float x, y, z;
    };
    
    // pointer to data member in multiple inheritance
    class B1
    {
    public:
        int v = 1;
    };
    class B2
    {
    public:
        int v = 2;
    };
    class D : public B1, public B2
    {
    public:
        int v = 3;
    };
    void findMemberByClassMemberPointer( int D::*dataMemberPoiner, D* d )
    {
        printf( "member value= %d\n", d->*dataMemberPoiner );
        //how to use data member pointer
    };
    int main( int argc, const char** argv )
    {
        // pointer to data member in single data
        float Point3d::*px = &Point3d::x;
        float Point3d::*py = &Point3d::y;
        float Point3d::*pz = &Point3d::z;
        float Point3d::*pnull = nullptr;
        printf( "float Point3d::*pnull = %p\n", pnull );
        printf( "&Point3d::x = %p\n", px );
        printf( "&Point3d::y = %p\n", py );
        printf( "&Point3d::z = %p\n", pz );
        if ( px == NULL || px == nullptr ) {
            printf( "px in compiler's angle is nullptr\n" );
        }
        {
            printf( "px is 0x0 but px in compiler's angle is not nullptr\n" );
        }
        // pointer to data member in multiple inheritance
        auto d = new D;
        auto drivenClassMemberPointer = &D::v;
        findMemberByClassMemberPointer( drivenClassMemberPointer, d );
        auto base2ClassMemberPointer = &B2::v;
        findMemberByClassMemberPointer( base2ClassMemberPointer, d );
    
        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

    输出

    float Point3d::*pnull = 0xffffffffffffffff
    &Point3d::x = (nil)
    &Point3d::y = 0x4
    &Point3d:😒 = 0x8
    px is 0x0 but px in compiler’s angle is not nullptr
    member value= 3
    member value= 2

  • 相关阅读:
    写给五年前的自己,即还在新手村的你
    前端架构基础 vue04 vue中的网络请求
    搜维尔科技:Varjo-最自然和最直观的互动
    linux中执行.sh文件出现/bin/sh^M: bad interpreter: No such file or directory
    OpenCascade模型解析-详细分解模型结构
    InputMethodManager输入法窗口为啥dumpsys是全屏?千里马带你疑难解惑输入法相关
    集合框架1
    第五届“传智杯”全国大学生计算机大赛(练习赛)水题题解
    【LeetCode】15. 三数之和
    SpringCloud常用组件
  • 原文地址:https://blog.csdn.net/weixin_43950087/article/details/126086857