Rust에서“팻 포인터”는 무엇입니까?
나는 이미 여러 문맥에서 "팻 포인터"라는 용어를 읽었지만 그것이 정확히 무엇을 의미하고 Rust에서 언제 사용되는지 잘 모르겠습니다. 포인터가 일반 포인터보다 두 배 큰 것 같지만 이유를 모르겠습니다. 또한 특성 개체와 관련이있는 것 같습니다.
"팻 포인터"라는 용어는 동적 크기 유형 (DST) (슬라이스 또는 특성 개체)에 대한 참조 및 원시 포인터를 참조하는 데 사용됩니다 . 팻 포인터는 포인터와 DST를 "완전하게"만드는 정보 (예 : 길이)를 포함합니다.
녹에서 가장 일반적으로 사용되는 유형은 하지 DSTS하지만, 컴파일 타임에 고정 된 크기를 가지고있다. 이러한 유형 은 Sized
특성을 구현 합니다 . (같은 동적 크기의 힙 버퍼를 관리에도 종류가 Vec<T>
) 있습니다 Sized
컴파일러가 바이트의 정확한 수를 알고로 Vec<T>
인스턴스가 스택에 소요됩니다. 현재 Rust에는 4 가지 종류의 DST가 있습니다.
슬라이스 ( [T]
및 str
)
유형 [T]
(모든 T
)은 동적으로 크기가 조정됩니다 (특수한 "문자열 슬라이스"유형도 그렇습니다 str
). 그렇기 때문에 일반적으로 참조 뒤에 &[T]
또는 로만 표시됩니다 &mut [T]
. 이 참조는 소위 "팻 포인터"입니다. 점검 해보자:
dbg!(size_of::<&u32>());
dbg!(size_of::<&[u32; 2]>());
dbg!(size_of::<&[u32]>());
이것은 (일부 정리와 함께) 인쇄합니다.
size_of::<&u32>() = 8
size_of::<&[u32; 2]>() = 8
size_of::<&[u32]>() = 16
따라서 일반적인 유형 u32
에 대한 참조는 배열에 대한 참조 와 마찬가지로 8 바이트 크기 [u32; 2]
입니다. 이 두 가지 유형은 DST가 아닙니다. 그러나 [u32]
DST와 마찬가지로 이에 대한 참조는 두 배입니다. 슬라이스의 경우 DST를 "완료"하는 추가 데이터는 단순히 길이입니다. 따라서의 표현 &[u32]
은 다음과 같이 말할 수 있습니다 .
struct SliceRef {
ptr: *const u32,
len: usize,
}
특성 개체 ( dyn Trait
)
특성 개체로 특성을 사용할 때 (즉, 유형이 지워지고 동적으로 전달됨) 이러한 특성 개체는 DST입니다. 예:
trait Animal {
fn speak(&self);
}
struct Cat;
impl Animal for Cat {
fn speak(&self) {
println!("meow");
}
}
dbg!(size_of::<&Cat>());
dbg!(size_of::<&dyn Animal>());
이것은 (일부 정리와 함께) 인쇄합니다.
size_of::<&Cat>() = 8
size_of::<&dyn Animal>() = 16
다시 말하지만 일반 유형 &Cat
이므로 크기는 8 바이트에 불과 Cat
합니다. 그러나 dyn Animal
특성 개체이므로 동적으로 크기가 조정됩니다. 따라서 &dyn Animal
크기는 16 바이트입니다.
특성 개체의 경우 DST를 완료하는 추가 데이터는 vtable (vptr)에 대한 포인터입니다. 여기서 vtable과 vptr의 개념을 완전히 설명 할 수는 없지만이 가상 디스패치 컨텍스트에서 올바른 메서드 구현을 호출하는 데 사용됩니다. vtable은 기본적으로 각 메서드에 대한 함수 포인터 만 포함하는 정적 데이터 조각입니다. 이를 통해 특성 객체에 대한 참조는 기본적으로 다음과 같이 표현됩니다.
struct TraitObjectRef {
data_ptr: *const (),
vptr: *const (),
}
(이것은 추상 클래스에 대한 vptr이 객체 내에 저장되는 C ++와 다릅니다. 두 접근 방식 모두 장점과 단점이 있습니다.)
커스텀 DST
실제로 마지막 필드가 DST 인 구조체를 사용하여 자신 만의 DST를 만들 수 있습니다. 그러나 이것은 다소 드문 경우입니다. 대표적인 예가 std::path::Path
.
A reference or pointer to the custom DST is also a fat pointer. The additional data depends on the kind of DST inside the struct.
Exception: Extern types
In RFC 1861, the extern type
feature was introduced. Extern types are also DSTs, but pointers to them are not fat pointers. Or more exactly, as the RFC puts it:
In Rust, pointers to DSTs carry metadata about the object being pointed to. For strings and slices this is the length of the buffer, for trait objects this is the object's vtable. For extern types the metadata is simply
()
. This means that a pointer to an extern type has the same size as ausize
(ie. it is not a "fat pointer").
But if you are not interacting with a C interface, you probably won't ever have to deal with these extern types.
Above, we've seen the sizes for immutable references. Fat pointers work the same for mutable references, immutable raw pointers and mutable raw pointers:
size_of::<&[u32]>() = 16
size_of::<&mut [u32]>() = 16
size_of::<*const [u32]>() = 16
size_of::<*mut [u32]>() = 16
참고URL : https://stackoverflow.com/questions/57754901/what-is-a-fat-pointer-in-rust
'development' 카테고리의 다른 글
빌드 프로세스의 일부로 NuGet 패키지 생성 자동화 (0) | 2020.11.25 |
---|---|
일부 프로토콜을 다른 프로토콜을 따르는 구체적인 유형으로 사용하는 것은 지원되지 않습니다. (0) | 2020.11.25 |
Delphi에서 스레딩을 수행하는 다양한 방법 중에서 어떻게 선택합니까? (0) | 2020.11.25 |
Spring MVC 명령 객체를 바인딩 할 때 매개 변수 이름을 사용자 정의하는 방법은 무엇입니까? (0) | 2020.11.25 |
sun.misc.Unsafe는 어디에 문서화되어 있습니까? (0) | 2020.11.25 |