【问题标题】:How to define a copyable struct containing a String? [duplicate]如何定义包含字符串的可复制结构? [复制]
【发布时间】:2016-07-11 10:28:04
【问题描述】:

我有一个这样的结构

#[derive(Copy, Clone)]
enum Command {
    Quit,
    Error { msg: String },
}

编译器抱怨它无法为Error 生成复制构造函数。

我需要使结构可复制以通过通道传递到另一个线程。

error: the trait `Copy` may not be implemented for this type; variant `Error` does not implement `Copy` [E0205]
#[derive(Copy, Clone)]
^~~~~~~~~~~~~~~~~~~~~~
note: in this expansion of #[derive_Copy] (defined in src/main.rs)

如果msgi32,则编译。这么基本的东西看起来很奇怪 键入为String 是不可复制的。

【问题讨论】:

  • StringCopyable 不同,Vec 不是。两者都处理堆分配的内容,因此不能用memcpy 安全地复制。本书相关页面:doc.rust-lang.org/book/strings.html
  • 我明白了,但我需要将对象传递给通道,并且它需要类型是可复制的。我从头到尾阅读了本教程,但内容很浅。
  • @DaneelS.Yaitskov 类型必须是可复制的才能通过通道传递。
  • 确实,只需要Send trait,它是由编译器自动派生的,并不暗示Copy。你应该认真找出真正的问题在哪里。请向我们展示更多代码并相应地改写问题。

标签: rust


【解决方案1】:

对于我来说,像 string 这样的基本类型是不可复制的,这看起来很奇怪。

Rust 首先是显式

C 程序员(尤其是 Linus Torvald)经常听到的关于 C++ 的抱怨之一是 C++ 中存在太多隐式复制,从而隐藏了内存分配。再加上隐式转换,它们真的可以潜入最意想不到的地方。

Rust 的设计目的是暴露底层操作的复杂性。它确实会隐式执行一些转换(从&T 借用到&Trait),但这些都是便宜(并且通常是恒定的时间)。

这种明确性体现在您在这里的两个特征中:

  • Clone 是关于指示如何创建一个新实例,并且必须显式调用。大多数类型(但不是全部)都可以使用它进行复制。

  • Copy 是一个特定的编译器特征,表示开发人员希望激活该类型的隐式复制;只有当浅拷贝等同于深拷贝时才可用,这样可以确保不会发生内存分配作为这些隐式拷贝的一部分

所以,为了确保您的评论:

  • String 是可复制的,使用 .clone()
  • String 不可隐式复制,因为这会导致不明显的内存分配发生

【讨论】:

    【解决方案2】:

    String 实际上是指向一些堆分配数据的指针,它的长度和容量。复制该信息会创建两个拥有的变量,它们都指向同一个堆分配的数据,这会破坏 Rust 的内存管理(您会遇到 use-after-free 问题)。

    也就是说,你的结构不需要实现Copy 来通过通道发送,它只需要是SizedString 是(因为编译器知道指针的大小) .发送带有String 的结构或枚举应该可以直接使用,而无需派生任何特征。

    【讨论】:

      猜你喜欢
      • 2018-05-24
      • 2018-07-14
      • 2015-05-20
      • 1970-01-01
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 2020-09-20
      • 2022-09-24
      相关资源
      最近更新 更多