Do数据成员地址位于(this)和(this+1)之间



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

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

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

它们一定是真的吗?(在我检查过的一些案例中,它们似乎是真的。)

编辑:我错过了和符号,现在它是不等式的正确形式。

来自CPP标准草案4713:

6.6.2对象模型[interro.Object]/7
可复制或标准布局类型(6.7)的对象应占用连续字节的存储空间。

12.2类成员[Class.mem]/18
分配具有相同访问控制(第14条)的(非联合)类的非静态数据成员,以便稍后的成员在类对象中具有更高的地址。

12.2类成员[Class.mem]/25
如果标准布局类对象有任何非静态数据成员,则其地址与其第一个非静态数据会员的地址相同。否则,其地址与其第一个基类子对象(如果有)的地址相同。

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

也来自在线cpp参考:

比较指向对象的两个指针(转换后)的结果定义如下:

1) 如果两个指针指向同一数组的不同元素,或指向同一阵列的不同元素内的子对象,则指向下标较高的元素的指针比较大。换句话说,比较指针的结果与比较它们所指向的元素的索引的结果相同。
2)如果一个指针指向数组的元素或数组元素的子对象,而另一个指针则指向数组最后一个元素之后的一个指针,则后一个指针的比较结果更大指向单个对象的指针被视为指向一个对象的数组的指针:&obj+1&obj(由于C++17)

因此,如果您的data_member而不是指针,并且没有单独分配内存,则您发布的公式保持有效至少是微不足道的可复制对象。

完整的标准文本相当于:

[expr.rel]-4:比较对象82的不相等指针的结果是根据符合以下规则的偏序定义的:

我们处理的是部分订单,而不是全部订单。这确实意味着a < bb < c暗示着a < c,但没有太多其他含义。

(注82指出,出于此目的,非数组对象被视为单个元素数组的元素,其直观含义/行为为"指针指向元素的一端")。

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

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

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

此规则只将指针与同一对象的数据成员相关,而不与不同对象的数据元素相关。

(4.3)否则,两个指针都不需要进行大于另一个的比较。

因此,您不会从标准中获得任何保证。你是否能找到一个真实世界的系统,在那里你会得到与你预期不同的结果,这是另一个问题。

对象的值在其表示中,该表示是一个无符号字符序列:〔basic.types〕/4

T类型对象的对象表示是T类型对象所占用的N个无符号字符对象的序列,其中N等于sizeof(T)。类型T的对象的值表示是参与表示类型T的值的比特集。〔…〕

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

读取或修改对象的值

那么子对象的值是完整对象值的一部分吗?我想这就是标准的意图。

如果将对象指针强制转换为unsigned char*,则比较结果应该为true。(这是一种常见的做法,属于不符合规范的核心问题#1701)

不,这里有一个反例

#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();
}

有可能的输出(如图所示)

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

注意,a_memberprint_b中由this指向的B之外

最新更新