|
|
|
@ -115,20 +115,16 @@ enum Foo {
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
struct FooRepr {
|
|
|
|
|
data: u64, // this is either a u64, u32, or u8 based on `tag`
|
|
|
|
|
data: u64, // 이것은 `tag`에 따라 u64, u32, 또는 u8 입니다.
|
|
|
|
|
tag: u8, // 0 = A, 1 = B, 2 = C
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
And indeed this is approximately how it would be laid out (modulo the
|
|
|
|
|
size and position of `tag`).
|
|
|
|
|
그리고 이것은 정말로 실제와 비슷하게 배치되는 것입니다 (`tag`의 위치와 크기에 따라).
|
|
|
|
|
|
|
|
|
|
However there are several cases where such a representation is inefficient. The
|
|
|
|
|
classic case of this is Rust's "null pointer optimization": an enum consisting
|
|
|
|
|
of a single outer unit variant (e.g. `None`) and a (potentially nested) non-
|
|
|
|
|
nullable pointer variant (e.g. `Some(&T)`) makes the tag unnecessary. A null
|
|
|
|
|
pointer can safely be interpreted as the unit (`None`) variant. The net
|
|
|
|
|
result is that, for example, `size_of::<Option<&T>>() == size_of::<&T>()`.
|
|
|
|
|
하지만 어떤 몇 가지 경우에서는 이런 표현은 비효율적입니다. 전통적인 경우는 러스트의 "널 포인터 최적화"입니다:
|
|
|
|
|
하나의 `()`을 가진 형(예를 들어 `None`)과 (중첩될 수도 있는) 널이 될 수 없는 포인터를 가진 형(예를 들어 `Some(&T)`)이 있는 열거형은 태그가 필요하지 않습니다. 널 포인터는 안전하게 `()` 형(`None`)으로 해석할 수 있거든요.
|
|
|
|
|
최종적인 결과는, 예를 들어, `size_of::<Option<&T>>() == size_of::<&T>()`이게 됩니다.
|
|
|
|
|
|
|
|
|
|
There are many types in Rust that are, or contain, non-nullable pointers such as
|
|
|
|
|
`Box<T>`, `Vec<T>`, `String`, `&T`, and `&mut T`. Similarly, one can imagine
|
|
|
|
|