首页 文章

数据成员地址介于(this)和(this 1)之间吗?

提问于
浏览
6

假设我们在成员函数中有以下两个不等式

this <=  (void *) &this->data_member

&this->data_member < (void *) (this+1)

他们保证是真的吗? (在我检查过的几个案例中,它们似乎都是真的 . )

编辑:我错过了&符号,现在这是不正当的正确形式 .

4 回答

  • 6

    从CPP标准草案4713:

    6.6.2对象模型[intro.object] / 7一个简单可复制或标准布局类型的对象(6.7)应占用连续的存储字节 . 12.2类成员[class.mem] / 18分配具有相同访问控制(第14章)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址 . 12.2类成员[class.mem] / 25如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同 . 否则,其地址与其第一个基类子对象(如果有)的地址相同 .

    综合以上所有内容,我们可以说第一个等式至少适用于可复制的对象 .

    也来自在线cpp reference

    比较两个指向对象的指针(转换后)的结果定义如下:1)如果两个指针指向同一个数组的不同元素,或指向同一个数组的不同元素内的子对象,则指向该元素的指针较高的下标比较大 . 换句话说,它们比较指针的结果与它们指向的元素的索引的比较结果相同 . 2)如果一个指针指向数组的元素,或指向数组元素的子对象,而另一个指针指向一个超过数组的最后一个元素的指针,则后一指针将指向更大的指针 . 指向单个对象的指针被视为指向一个数组的指针:&obj 1比较大于&obj(因为C 17)

    因此,如果您的 data_membernot 指针并且没有单独分配内存,那么您发布的方程式至少可以保留至少可复制的对象 .

  • 0

    不,这是一个反例

    #include <iostream>
    
    struct A
    {
        int a_member[10];    
    };
    
    struct B : public virtual A
    {
        int b_member[10];
        void print_b() { std::cout << static_cast<void*>(this) << " " << static_cast<void*>(std::addressof(this->a_member)) << " " << static_cast<void*>(this + 1) << std::endl; }
    };
    
    struct C : public virtual A
    {
        int c_member[10];    
        void print_c() { std::cout << static_cast<void*>(this) << " " << static_cast<void*>(std::addressof(this->a_member)) << " " << static_cast<void*>(this + 1) << std::endl; }
    };
    
    struct D : public B, public C 
    {
        void print_d() 
        { 
            print_b();
            print_c();
        }
    };
    
    int main()
    {
        D d;
        d.print_d();
    }
    

    使用可能的输出(作为seen here

    0x7fffc6bf9fb0 0x7fffc6bfa010 0x7fffc6bfa008
    0x7fffc6bf9fe0 0x7fffc6bfa010 0x7fffc6bfa038
    

    请注意 a_member 位于 this 指向的 B 之外 print_b

  • 0

    对象的值在其表示内,并且此表示是一个unsigned char序列:[basic.types]/4

    类型T的对象的对象表示是由类型T的对象占据的N个无符号字符对象的序列,其中N等于sizeof(T) . 类型T的对象的值表示是参与表示类型T的值的位集 . [...]

    因此,对于形式主义原教旨主义者来说,确实没有定义 Value ,但这一术语出现在访问的定义中:[defns.access]

    读取或修改对象的值

    那么完整对象的值的子对象部分的值是什么?我想这是标准的意图 .

    如果将对象指针转换为 unsigned char* ,则比较应为true . (这是一种常见的做法,属于规格不足core issue #1701

  • 4

    完整standard text相当于:

    [expr.rel] - 4:比较不等指针到对象82的结果是根据与以下规则一致的部分顺序定义的:

    我们在这里处理的是部分订单,而不是总订单 . 这确实意味着 a < bb < c 意味着 a < c ,但其他并不多 .

    (注82)为了这个目的,非数组对象被认为是单元素数组的元素,具有“指向元素一的结尾指针”的直观含义/行为 .

    (4.1)如果两个指针指向同一个数组的不同元素或其子对象,则指向具有较高下标的元素的指针需要比较更大 .

    指向不同成员的指针不是指向同一数组的元素(子对象)的指针 . 此规则不适用 .

    (4.2)如果两个指针指向同一对象的不同非静态数据成员,或者指向这些成员的子对象,则递归地指向稍后声明的成员的指针需要比较更大,前提是两个成员具有相同的访问控制([class.access]),两个成员都不是零大小的子对象,并且它们的类不是联合 .

    此规则仅将指针与同一对象的数据成员相关联,而不是指向不同对象的数据成员 .

    (4.3)否则,两个指针都不需要比另一个更大 .

    因此,您没有得到标准的任何保证 . 你是否能找到一个真实世界的系统,你得到的结果与你预期的不同是另一个问题 .

相关问题