繁体   English   中英

如果字符串的生命周期是静态的,如何通过引用拥有字符串?

[英]How can I own a string through reference if its lifetime is static?

在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类型

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的大小减小为三个指针大小,其中一个插槽用于区分符,其余两个用于字符串切片。 不利之处在于,它需要为所有者字符串的情况进行额外的分配和间接寻址-但如果您的大多数类名都来自静态字符串切片,则它可能仍会奏效。

您可以允许使用多种类型的方法是使用Into特性。 这是通用的,因为它可以确保类型之间的安全转换。

这样, str切片可以“转换为”拥有的String

一些测试代码来演示它:

#[derive(Debug)]
struct Test {
    name: String,
}

impl Test {
    pub fn new<T: Into<String>>(t: T) -> Test {
        Test { name: t.into() }
    }
}

fn main() {
    let t = Test::new("a");
    println!("{:?}", t);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM