如果类型相同,对象地址必须不同,但如果类型不同,地址可以相同
Reason behind that object addresses must differ if types are the same, but addresses can be the same if types differ
我们有空的基类优化。请看以下两种情况:
案例 A
struct Empty1 { };
struct Empty2 { };
struct One: Empty1, Empty2 { };
在这里,sizeof(One)
是 1。Empty1
和Empty2
的地址相同。
案例B
struct Empty { };
struct Empty1: public Empty { };
struct Empty2: public Empty { };
struct Two: Empty1, Empty2 { };
在这里,sizeof(Two)
是 2。Empty1
和Empty2
的地址不同,因为它们都有Empty
(这些Empty
应该有不同的地址)。
为什么标准允许不同类型使用相同的地址,但不允许相同类型?此规则避免了什么问题?
如果我创建一个tuple
实现,其中所有空成员都将具有相同的地址(无论其类型如何),我会遇到什么问题?
地址是对象标识的一部分。具有单独地址的相同类型的单独对象是一般规则。这就是您如何知道有多个对象。
在复制构造函数中,您通常可以找到自赋值if (this != &other)
的测试。如果同一类型的不同对象具有相同的地址,则此操作将失败。
无论如何,不同类型的对象都无法像这样进行比较,所以不是问题。我们还有一个结构体及其第一个成员,一个数组和第一个元素,它们具有相同的地址,但类型不同。
空基类在这里会带来问题,但仅当有两个相同类型的基类,或者基类恰好与派生类的第一个成员属于同一类型时。因此,在这些情况下,有特殊的规则禁止两个相同物体的重叠。
这个想法是它们应该是两个独立的子对象,并在this != &that
测试中工作。
该规则在标准 [intro.object] 中说明:
除非对象是位字段或大小为零的基类子对象,否则该对象的地址是地址 它占用的第一个字节。两个具有重叠生存期但不是位字段的对象 a 和 b 可能具有 如果一个嵌套在另一个中,或者至少有一个是零大小的基类子对象,则使用相同的地址,并且 它们属于不同的类型;否则,它们具有不同的地址。
空基类属于此规则的一个原因是因为 可以将空的基类引用强制转换为基对象的引用。
最好的是看到它的实际效果,我添加了 gcc 生成的程序集和 -O3 优化:
struct Empty1 { };
struct Empty2 { };
struct One: Empty1, Empty2 {
int i;
};
struct Other{
int i;
};
//an Empty and a One may have the same address
int f(Empty1& a,One& b){ mov DWORD PTR [rsi], 12 //write to *rsi
b.i=12; mov DWORD PTR [rdi], 15 //may be rsi==rdi
auto& a_one = mov eax, DWORD PTR [rsi] //reload from *rsi
static_cast<One&>(a); ret
a_one.i=15;
return b.i;
}
//an int and a One may have the same address
int f(int& a,One& b){ mov DWORD PTR [rsi], 12 //write to *rsi
b.i=12; mov DWORD PTR [rdi], 15 //may be rsi==rdi
a=15; mov eax, DWORD PTR [rsi] //reload from *rsi
return b.i; ret
}
//a long can not have the same address as a One
int f(long& a,One& b){ mov DWORD PTR [rsi], 12
b.i=12; mov eax, 12 //aliasing optimization
a=15; mov QWORD PTR [rdi], 15 //sure rsi!=rdi aliasing rule
return b.i; ret
}
//the int inside and Other can alias an int inside a One
int f(Other& a,One& b){ mov DWORD PTR [rsi], 12
b.i=12; mov eax, 12 //aliasing optimization
a.i=15; mov QWORD PTR [rdi], 15 //sure rsi!=rdi aliasing rule
return b.i; ret
}
给定地址只能存在一个完整的对象。完整的对象是未嵌套在另一个对象中的对象。
必须在同一地址(没有 UB)以相同的类型反对是不可能的。但是由于您的对象是空的,因此优化的元组中不需要多个对象。您只需要实现一个get<I>
,该引用所有Is
的同一对象,这些旨在引用同一空类的对象。
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 我可以直接为指针分配地址吗?如果是,如何做到这一点
- 如果我有指向基类对象的指针,如何获取虚拟方法的地址?
- 如果堆栈在数字较低的地址增长,为什么指针比较会逆转这种情况?
- 如果地址已知,如何获取指针变量的名称
- 如果嵌套对象具有相同的地址,编译器如何区分它们?
- 如果 C/C++ 指针是"just"地址,为什么它们需要具有类型?
- 如果地址-B访问倾向于访问地址-C访问,则缓存可以识别
- 如果类型相同,对象地址必须不同,但如果类型不同,地址可以相同
- 如果我进行地址,则可以保证静态变量
- 如果在循环中声明了指针变量,则它是否与循环的每次传递都与相同的内存地址相关联
- 如果仅使用clang编译主应用程序,则可以使用clang地址清理器吗?
- 如果您使一个char*ptr存储整数变量的地址,会发生什么
- 如果指定了参数,如何将地址分配给函数指针
- (C++内存管理)如果我们有一个 int x = 1234,并且 int &y = x...那么堆栈上 y 的地址是什么?
- 如果知道IP地址,我可以拍摄远程机器的屏幕截图吗
- 字符 * 名称 = "Duncan" 怎么可能 ;如果指针只能保存地址,是否有效?
- 如果用调试信息编译,则通过其名称获取全局变量地址
- 如果最后一个地址是0xFFFFFFFF,我如何获取数组结束后的地址
- 是否有例外的规则,如果地址可以使用 &它是左值?