Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果类型相同,则对象地址必须不同,但如果类型不同,则地址可以相同_C++ - Fatal编程技术网

C++ 如果类型相同,则对象地址必须不同,但如果类型不同,则地址可以相同

C++ 如果类型相同,则对象地址必须不同,但如果类型不同,则地址可以相同,c++,C++,我们有空的基类优化。看看这两种情况: 案例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 { };

我们有空的基类优化。看看这两种情况:

案例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
应该有不同的地址)

为什么标准允许不同类型使用相同的地址,但不允许相同类型使用相同的地址?这个规则避免了什么问题


如果我创建一个
元组
实现,其中所有空成员将具有相同的地址(无论其类型如何)?

地址是对象标识的一部分。具有单独地址的相同类型的单独对象是一条一般规则。这就是为什么你知道有不止一个物体

在复制构造函数中,如果(this!=&other)
,通常可以找到一个自赋值测试
。如果相同类型的不同对象具有相同的地址,则此操作将失败

不同类型的对象无论如何都不能像这样进行比较,所以这不是问题。我们还有一个结构和它的第一个成员,还有一个数组和第一个元素,它们有相同的地址,但类型不同

空基类在这里会造成问题,但前提是您有两个相同类型的基类,或者该基类恰好与派生类的第一个成员的类型相同。因此,在这些情况下,有专门的规则禁止两个相同对象的重叠


其思想是,它们应该是两个独立的子对象,并在
this!=&标准[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                        
}                                        
struct Empty1{};
结构清空2{};
结构1:Empty1,Empty2{
int i;
};
结构其他{
int i;
};
//一个空的和一个可能有相同的地址
intf(空1&a,1&b){mov DWORD PTR[rsi],12//写入*rsi
b、 i=12;mov-DWORD PTR[rdi],15//可能是rsi==rdi
auto&a_one=mov eax,DWORD PTR[rsi]//从*rsi重新加载
静态铸造(a);翻新
a_1.i=15;
返回b.i;
}    
//int和One可能具有相同的地址
intf(int&a,One&b){mov DWORD PTR[rsi],12//写入*rsi
b、 i=12;mov-DWORD PTR[rdi],15//可能是rsi==rdi
a=15;mov eax,DWORD PTR[rsi]//从*rsi重新加载
返回b.i;返回
}        
//long的地址不能与long的地址相同
国际货币基金组织(长期、长期、长期和长期){mov DWORD PTR[rsi],12
b、 i=12;mov-eax,12//混叠优化
a=15;mov QWORD PTR[rdi],15//sure rsi!=rdi别名规则
返回b.i;返回
}   
//int-inside和Other可以在一个内部别名一个int
int f(其他a、1和b){mov DWORD PTR[rsi],12
b、 i=12;mov-eax,12//混叠优化
a、 i=15;mov QWORD PTR[rdi],15//sure rsi!=rdi别名规则
返回b.i;返回
}                                        
给定地址只能存在一个完整的对象。完整对象是未嵌套在另一个对象中的对象


必须在同一地址(没有UB)使用同一类型的对象是不可能成功的。但由于对象是空的,所以在优化的元组中不需要多个对象。您只需要实现一个
get
,它为所有
Is
引用同一个对象,这些对象都指向同一个空类的对象。

在您的示例中,您讨论的是基类。在你关于元组成员的问题中。有两件事似乎很重要unrelated@ArtemyVysotsky当前位置有两个问题,我认为这两个问题高度相关(它们都是关于对象的地址相同)。而
元组
通常是通过继承实现的,其中使用了EBO。我想说的是规则是从C继承的。您可能有
空的数组
。所以sizeof不能是
0
。谢谢你的回答!对于空类,赋值是一个空函数(因为它没有可复制的内容),不是吗?所以你不会在里面写身份测试,但会发生什么问题呢?由于类为空,没有非静态成员,因此似乎不需要使用self进行测试。@Jarod42-这是一个示例,说明您需要知道是否有一个或两个对象,并使用它们的地址进行测试。具有单独地址的相同类型的单独对象是一条一般规则。例如,如果无法区分基类和派生类的第一个成员,为什么要将它们区分开来?@BoPersson:“相同类型的独立对象具有独立的ad?”