创建零大小结构的多种方法之间有什么区别? [英] What are the differences between the multiple ways to create zero-sized structs?
问题描述
我发现了四种创建没有数据的 struct
的不同方法:
I found four different ways to create a struct
with no data:
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
struct C(()); // unit-valued tuple struct
struct D; // unit struct
(我将任意嵌套的元组只包含()
和单变量 enum
声明排除在外,因为我知道为什么不应该这样做被使用).
(I'm leaving arbitrarily nested tuples that contain only ()
s and single-variant enum
declarations out of the question, as I understand why those shouldn't be used).
这四个声明之间有什么区别?我将它们用于特定目的还是可以互换?
What are the differences between these four declarations? Would I use them for specific purposes, or are they interchangeable?
这本书和参考文献出奇地无助.我确实找到了此已接受的RFC( clarified_adt_kinds)之间的区别,即单元结构也声明了常量值 D
,而元组结构也声明了构造函数 B()
和 C(_:())
.但是,它没有提供关于为什么使用它的设计指南.
The book and the reference were surprisingly unhelpful. I did find this accepted RFC (clarified_adt_kinds) which goes into the differences a bit, namely that the unit struct also declares a constant value D
and that the tuple structs also declare constructors B()
and C(_: ())
. However it doesn't offer a design guideline on why to use which.
我的猜测是,当我使用 pub
导出它们时,实际上可以在模块外部构造种类的方法有所不同,但是我没有找到关于此的结论性文件.
My guess would be that when I export them with pub
, there are differences in which kinds can actually be constructed outside of my module, but I found no conclusive documentation about that.
推荐答案
这四个定义之间只有两个功能上的区别(这是我稍后会提到的第五种可能性):
There are only two functional differences between these four definitions (and a fifth possibility I'll mention in a minute):
- 语法(最明显).麦卡顿的答案更加详细.
- 将结构标记为
pub
时,是否其构造函数(也称为struct
文字语法)可在其定义的模块之外使用.
- Syntax (the most obvious). mcarton's answer goes into more detail.
- When the struct is marked
pub
, whether its constructor (also calledstruct
literal syntax) is usable outside the module it's defined in.
您的唯一一个不能从当前模块外部直接构造的示例是 C
.如果您尝试执行此操作,则会收到错误消息:
The only one of your examples that is not directly constructible from outside the current module is C
. If you try to do this, you will get an error:
mod stuff {
pub struct C(());
}
let _c = stuff::C(()); // error[E0603]: tuple struct `C` is private
之所以会这样,是因为该字段未标记为 pub
;如果将 C
声明为 pub struct C(pub())
,该错误就会消失.
This happens because the field is not marked pub
; if you declare C
as pub struct C(pub ())
, the error goes away.
您没有提到的另一种可能性是给出了更具描述性的错误消息:普通结构,大小为零的非 pub
成员.
There's another possibility you didn't mention that gives a marginally more descriptive error message: a normal struct, with a zero-sized non-pub
member.
mod stuff {
pub struct E {
_dummy: (),
}
}
let _e = stuff::E { _dummy: () }; // error[E0451]: field `_dummy` of struct `main::stuff::E` is private
(同样,您可以通过使用 pub
进行声明,使 _dummy
字段在模块外部可用.)
(Again, you can make the _dummy
field available outside of the module by declaring it with pub
.)
由于 E
的构造函数仅可在 stuff
模块内使用,因此 stuff
对的时间和方式具有独占控制权E
已创建.标准库中的许多结构都利用了这一点,例如 Box
(举一个明显的例子).零大小类型的工作方式完全相同;实际上,从模块定义的外部,您唯一知道不透明类型为零大小的方法是调用
Since E
's constructor is only usable inside the stuff
module, stuff
has exclusive control over when and how values of E
are created. Many structs in the standard library take advantage of this, like Box
(to take an obvious example). Zero-sized types work in exactly the same way; in fact, from outside the module it's defined in, the only way you would know that an opaque type is zero-sized is by calling mem::size_of
.
这篇关于创建零大小结构的多种方法之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!