rust - 如果它的生命周期是静态的,我如何通过引用拥有一个字符串?

标签 rust

在 Rust 中,我想给一个类起一个名字,这个类拥有这个名字。

有时名称由 String 传递。对于这种情况,我可以简单地移动所有权。

但有时这个名称是由静态字符串(&str)给出的。 对于这种情况,我想引用该字符串,而不是从中创建一个 String

我的问题是:如何在我的类中声明这个名称字段? 应该是什么类型?


关于要求的一些更新/背景:

  • 名称将是不可变的。
  • 之所以要区分一个String和一个&str,是因为我想把动态分配减到最少。

最佳答案

一个选项是将名称成员声明为枚举,它可以包含 String&'static str:

enum Name {
    Static(&'static str),
    Owned(String),
}

struct Class {
    name: Name,
    // ...
}

然后该类可以提供适当的构造函数(必须有两个)和一个 get_name() 方法来访问作为字符串切片的名称:

impl Class {
    pub fn new_from_str(name: &'static str) -> Class {
        Class { name: Name::Static(name) }
    }
    pub fn new_from_owned(name: String) -> Class {
        Class { name: Name::Owned(name) }
    }

    pub fn get_name(&self) -> &str {
        match self.name {
            Name::Owned(ref s) => s.as_str(),
            Name::Static(s) => s,
        }
    }
}

fn main() {
    let c1 = Class::new_from_str("foo");
    let c2 = Class::new_from_owned("foo".to_string());
    println!("{} {}", c1.get_name(), c2.get_name());
}

另一种选择是使用 Cow type标准库为此目的提供:

use std::borrow::Cow;

struct Class {
    name: Cow<'static, str>,
}

由于 Cow 实现了 Into 特性,现在可以将构造函数编写为单个通用函数:

pub fn new<T>(name: T) -> Class
    where T: Into<Cow<'static, str>> {
    Class { name: name.into() }
}

Cow 还实现了 Deref 特性,允许将 get_name() 写成:

pub fn get_name(&self) -> &str {
    return &self.name;
}

在这两种情况下,name 成员将等于较大变体的大小加上鉴别器占用的空间。由于 String 是这里较大的类型,它占用了三个指针大小(字符串内容单独分配,不算在内), Name 将占用四个指针大小全部的。在显式 enum 的情况下,可以通过装箱字符串使成员更小:

enum Name {
    Static(&'static str),
    Owned(Box<String>),
}

这会将 Name 的大小缩减为三个指针大小,其中一个槽用于鉴别器,其余两个用于字符串切片。缺点是它需要为自有字符串情况进行额外的分配和间接访问 - 但如果您的大部分类名来自静态字符串切片,它仍然可能会有所返回。

关于rust - 如果它的生命周期是静态的,我如何通过引用拥有一个字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40728768/

相关文章:

macros - 为什么通过 `use some_crate::derive_foo` 导入自定义派生 Foo 不起作用?

c++ - 如何在提交时自动格式化 Rust(和 C++)代码?

rust - 如何使 cargo 保存分析?

multithreading - 为什么 `thread::JoinHandle<T>` 有一个类型参数?

rust - 如何将字段添加到 GraphQL Union 类型的 GraphQL 结构? (Rust 枚举和 Juniper)

rust - 迭代获取子节点的可变引用

ubuntu - Rust Ubuntu 20.04.1安装问题

rust - Rust 中 libc::stat 中的文件参数

rust - 使用线程时 Rust 中 self 参数的生命周期

ruby - 为什么我的 rust 程序比 ruby​​ 程序慢?