我如何编写一个函数来获取拥有的和非拥有的字符串集合? [英] How do I write a function that takes both owned and non-owned string collections?

查看:38
本文介绍了我如何编写一个函数来获取拥有的和非拥有的字符串集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在编写将字符串集合作为参数的函数时遇到问题.我的函数如下所示:

I'm having trouble writing a function that takes a collection of strings as parameter. My function looks like this:

type StrList<'a> = Vec<&'a str>;

fn my_func(list: &StrList) {
    for s in list {
        println!("{}", s);
    }
}

如果我按预期将 Vec<&'a str> 传递给函数,一切都会顺利.但是,如果我传递 Vec 编译器会抱怨:

All goes well if I pass a Vec<&'a str> to the function, as expected. However, if I pass a Vec<String> the compiler complains:

error[E0308]: mismatched types
  --> src/main.rs:13:13
   |
13 |     my_func(&v2);
   |             ^^^ expected &str, found struct `std::string::String`
   |
   = note: expected type `&std::vec::Vec<&str>`
   = note:    found type `&std::vec::Vec<std::string::String>`

这是主要使用的:

fn main() {
    let v1 = vec!["a", "b"];
    let v2 = vec!["a".to_owned(), "b".to_owned()];
    my_func(&v1);
    my_func(&v2);
}

我的函数无法获取拥有字符串的向量.相反,如果我将 StrList 类型更改为:

My function is not able to take vectors of owned strings. Conversely, if I change the StrList type into:

type StrList = Vec<String>;

第一个调用失败,第二个调用成功.

The first call fails, and the second works.

一种可能的解决方案是以这种方式从 v2 生成 Vec<&'a str> :

A possible solution is to produce a Vec<&'a str> from v2 in this way:

let v2_1 : Vec<_> = v2.iter().map(|s| s.as_ref()).collect();

但对我来说似乎很奇怪.my_func 不应该关心字符串的所有权.

But it seems very odd to me. my_func should not care about the ownership of the strings.

我应该为 my_func 使用什么样的签名来支持拥有的字符串向量和字符串引用?

What kind of signature should I use for my_func to support both vectors of owned strings and string references?

推荐答案

虽然 String&str 的关系非常密切,但它们并不完全相同.这是您的向量在内存中的样子:

Although String and &str are very closely related, they are not identical. Here's what your vectors look like in memory:

v1 ---> [ { 0x7890, // pointer to "a" + 7 unused bytes
            1 }     // length of "a"
          { 0x7898, // pointer to "b" + 7 unused bytes
            1 } ]   // length

v2 ---> [ { 0x1230 // pointer to "a" + 7 unused bytes (a different copy)
            8      // capacity
            1 }    // length
          { 0x1238 // pointer ...
            8      // capacity
            1 } ]  // length

这里每一行都是相同数量的内存(四个或八个字节,取决于指针大小).你不能把其中一个的记忆当作另一个来对待.内存布局不匹配.这些物品的大小不同,布局也不同.例如,如果 v1 存储从地址 X 开始的项,v2 存储从地址 Y 开始的项,那么 v1[1] 在地址 X + 8v2[1] 在地址 Y + 12.

Here each line is the same amount of memory (four or eight bytes depending on pointer size). You can't take the memory of one of these and treat it like the other. The memory layout doesn't match up. The items are of different sized and have different layout. For example, if v1 stores its items starting at address X and v2 stores its items starting at address Y, then v1[1] is at address X + 8 but v2[1] is at address Y + 12.

可以做的是编写一个这样的通用函数:

What you can do is write a generic function like this:

fn my_func<T: AsRef<str>>(list: &[T]) {
    for s in list {
        println!("{}", s.as_ref());
    }
}

然后编译器可以为 &[String]&[&str] 以及其他类型生成适当的代码,如果它们实现了 AsRef.

Then the compiler can generate appropriate code for both &[String] and &[&str] as well as other types if they implement AsRef<str>.

这篇关于我如何编写一个函数来获取拥有的和非拥有的字符串集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆