![]() |
1
117
值类型不支持继承的原因是数组。
问题是,由于性能和GC原因,值类型数组存储为“inline”。例如,给定
现在,假设我们有了值类型的继承。当与上述数组的“内联存储”行为结合在一起时,就会发生一些不好的事情,正如我们所看到的那样。 in C++ . 考虑这个伪C代码:
根据正常转换规则,a
我们有问题是因为
(是的,这是一个令人讨厌的程序集,但关键是我们将在已知的编译时常量处通过数组递增,而不知道正在使用派生类型。)
所以,如果这真的发生了,我们会有内存损坏的问题。具体来说,在
尝试调试 那 ! |
![]() |
2
65
假设结构支持继承。然后声明:
这意味着结构变量没有固定的大小,这就是为什么我们有引用类型。 更好的是,考虑一下:
|
![]() |
3
14
结构不使用引用(除非它们被装箱,但您应该尽量避免这样做),因此多态性没有意义,因为没有通过引用指针进行间接寻址。对象通常位于堆上,并通过引用指针引用,但结构是在堆栈上分配的(除非已装箱),或是在堆上引用类型占用的内存中“内部”分配的。 |
![]() |
4
8
这里是什么 the docs 说:
基本上,它们应该保存简单的数据,因此没有继承等“额外特性”。从技术上讲,它们可能支持某种有限的继承(而不是多态性,因为它们位于堆栈中),但我认为,不支持继承也是一种设计选择(就像.NET语言中的许多其他东西一样)。
另一方面,我同意继承的好处,我认为我们都达到了我们想要的程度。
|
![]() |
5
3
类继承是不可能的,因为结构直接放置在堆栈上。继承结构比它的父结构要大,但JIT不知道这一点,它试图在太少的空间上放置太多的空间。听起来有点不清楚,我们来举个例子:
如果可能的话,它将崩溃在以下代码片段上:
空间分配给sizeof a,而不是sizeof b。 |
![]() |
6
3
有一点我想纠正。尽管结构不能被继承的原因是因为它们位于堆栈上是正确的,但这是一个半正确的解释。结构,与任何其他值类型一样 可以 生活在堆栈中。因为它将取决于变量的声明位置,所以它们要么位于 堆栈 或者在 堆 . 当它们分别是局部变量或实例字段时,就会出现这种情况。 这么说,塞西尔有一个正确的名字。 我想强调一下,价值类型 可以 生活在堆栈上。这并不意味着他们总是这样做。局部变量,包括方法参数,将。其他人都不会。然而,这仍然是他们不能被继承的原因。-) |
![]() |
7
3
结构是在堆栈上分配的。这意味着值语义非常自由,访问结构成员非常便宜。这并不能阻止多态性。 可以让每个结构以指向其虚拟函数表的指针开头。这将是一个性能问题(每个结构都至少有指针大小),但它是可行的。这将允许虚拟函数。 添加字段怎么样? 好吧,当您在堆栈上分配一个结构时,您将分配一定的空间。所需空间在编译时确定(无论是提前还是在抖动时)。如果添加字段,然后分配给基类型:
这将覆盖堆栈的某些未知部分。 另一种方法是运行时仅将sizeof(a)字节写入任何变量,以防止出现这种情况。 如果B重写A中的一个方法并引用它的integer2字段,会发生什么?要么运行时抛出一个memberAccessException,要么该方法访问堆栈上的一些随机数据。这些都是不允许的。 拥有结构继承是完全安全的,只要您不使用多态结构,或者在继承时不添加字段。但这些并不是非常有用。 |
![]() |
8
2
这似乎是一个非常常见的问题。我想补充一点,值类型存储在您声明变量的“就地”;除了实现细节之外,这意味着 不 表示关于对象的内容的对象头, 只有 变量知道驻留在那里的数据类型。 |
![]() |
9
1
结构确实支持接口,所以您可以这样做一些多态的事情。 |
![]() |
10
0
IL是一种基于堆栈的语言,因此使用参数调用方法的过程如下:
当方法运行时,它会从堆栈中弹出一些字节以获取其参数。它知道 确切地 由于参数是引用类型指针(在32位上总是4个字节),或者它是一个值类型,其大小总是精确已知,所以要弹出多少字节。 如果它是一个引用类型指针,那么该方法将查找堆中的对象并获取其类型句柄,该句柄指向一个方法表,该表为该确切类型处理该特定方法。如果是值类型,则不需要查找方法表,因为值类型不支持继承,因此只有一种可能的方法/类型组合。 如果值类型支持继承,那么会有额外的开销,因为结构的特定类型必须放置在堆栈及其值上,这意味着对该类型的特定具体实例进行某种方法表查找。这将消除价值类型的速度和效率优势。 |
![]() |
cobb208 · Malloc正在为释放指针引发错误 2 年前 |
![]() |
kernel · 打印结构数组内容时出错 2 年前 |
![]() |
mwitz · 在Rust中无法正确写入结构的函数属性 2 年前 |
![]() |
Ulysses · 无法访问结构字段(Rust) 2 年前 |
![]() |
Tor · 使用Box<None>值初始化struct 2 年前 |
![]() |
Yestin · Golang如何初始化数组结构[duplicate] 2 年前 |