创建零大小结构体的多种方法之间有什么区别?

2024-02-18

我发现了四种不同的方法来创建struct没有数据:

  • struct A{} // empty struct / empty braced struct
    
  • struct B(); // empty tuple struct
    
  • struct C(()); // unit-valued tuple struct
    
  • struct D; // unit struct
    

(我留下任意嵌套的元组,其中仅包含()s 和单变体enum声明是不可能的,因为我理解为什么不应该使用这些声明)。

有什么区别这四个声明之间?我会将它们用于特定目的,还是可以互换?

令人惊讶的是,这本书和参考资料毫无帮助。我确实找到了这个接受的 RFC (clarified_adt_kinds) https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md这有点不同,即单位结构也声明了一个常量值D并且元组结构还声明构造函数B() and C(_: ())。然而,它没有提供关于为什么使用哪个的设计指南。

我的猜测是,当我导出它们时pub,在我的模块之外实际上可以构建哪些类型存在差异,但我没有找到关于这一点的结论性文档。


这四个定义之间只有两个功能差异(我稍后会提到第五种可能性):

  1. 语法(最明显的)。麦卡顿的回答 https://stackoverflow.com/a/50170328/3650362更详细的内容。
  2. 当结构体被标记时pub,无论是构造函数 https://doc.rust-lang.org/nomicon/constructors.html(也叫struct字面语法 http://words.steveklabnik.com/structure-literals-vs-constructors-in-rust) 可在其定义的模块外部使用。

唯一不能从当前模块外部直接构造的示例是C。如果您尝试这样做,您将收到错误消息:

mod stuff {
    pub struct C(());
}
let _c = stuff::C(());  // error[E0603]: tuple struct `C` is private

发生这种情况是因为该字段未标记pub;如果你声明C as pub struct C(pub ()),错误消失。

您没有提到的另一种可能性会给出稍微更具描述性的错误消息:一个正常的结构,具有零大小的非pub member.

mod stuff {
    pub struct E {
        _dummy: (),
    }
}
let _e = stuff::E { _dummy: () };  // error[E0451]: field `_dummy` of struct `main::stuff::E` is private

(同样,您可以使_dummy通过声明它在模块外部可用的字段pub.)

Since E的构造函数只能在stuff模块,stuff对何时以及如何值具有独家控制权E被创建。标准库中的许多结构都利用了这一点,例如Box(举一个明显的例子)。零大小类型的工作方式完全相同;事实上,从定义它的模块外部,您知道不透明类型为零大小的唯一方法是调用mem::size_of https://doc.rust-lang.org/std/mem/fn.size_of.html.

See also

  • 创建无法在其板条箱外部实例化的零大小结构的惯用方法是什么? https://stackoverflow.com/q/64651511/3650362
  • 为什么要定义一个具有单位类型的单个私有字段的结构体? https://stackoverflow.com/q/63338208/3650362
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建零大小结构体的多种方法之间有什么区别? 的相关文章

随机推荐