Cannot split a string into string slices with explicit lifetimes because the string does not live long enough

后端 未结 2 1086
[愿得一人]
[愿得一人] 2020-12-22 08:38

I\'m writing a library that should read from something implementing the BufRead trait; a network data stream, standard input, etc. The first function is suppose

相关标签:
2条回答
  • 2020-12-22 09:21

    Your problem can be reduced to this:

    fn foo<'a>() {
        let thing = String::from("a b");
        let parts: Vec<&'a str> = thing.split(" ").collect();
    }
    

    You create a String inside your function, then declare that references to that string are guaranteed to live for the lifetime 'a. Unfortunately, the lifetime 'a isn't under your control — the caller of the function gets to pick what the lifetime is. That's how generic parameters work!

    What would happen if the caller of the function specified the 'static lifetime? How would it be possible for your code, which allocates a value at runtime, to guarantee that the value lives longer than even the main function? It's not possible, which is why the compiler has reported an error.

    Once you've gained a bit more experience, the function signature fn foo<'a>() will jump out at you like a red alert — there's a generic parameter that isn't used. That's most likely going to mean bad news.


    return a populated struct filled mostly with &'a str

    You cannot possibly do this with the current organization of your code. References have to point to something. You are not providing anywhere for the pointed-at values to live. You cannot return an allocated String as a string slice.

    Before you jump to it, no you cannot store a value and a reference to that value in the same struct.

    Instead, you need to split the code that creates the String and that which parses a &str and returns more &str references. That's how all the existing zero-copy parsers work. You could look at those for inspiration.

    String has lower performance than &str

    No, it really doesn't. Creating lots of extraneous Strings is a bad idea, sure, just like allocating too much is a bad idea in any language.

    0 讨论(0)
  • 2020-12-22 09:31

    Maybe the following program gives clues for others who also also having their first problems with lifetimes:

    fn main() {
        // using String und &str Slice
        let my_str: String = "fire".to_owned();
        let returned_str: MyStruct = my_func_str(&my_str);
        println!("Received return value: {ret}", ret = returned_str.version);
    
        // using Vec<u8> und &[u8] Slice
        let my_vec: Vec<u8> = "fire".to_owned().into_bytes();
        let returned_u8: MyStruct2 = my_func_vec(&my_vec);
        println!("Received return value: {ret:?}", ret = returned_u8.version);
    }
    
    
    // using String -> str
    fn my_func_str<'a>(some_str: &'a str) -> MyStruct<'a> {
        MyStruct {
            version: &some_str[0..2],
        }
    }
    
    struct MyStruct<'a> {
        version: &'a str,
    }
    
    
    // using Vec<u8> -> & [u8]
    fn my_func_vec<'a>(some_vec: &'a Vec<u8>) -> MyStruct2<'a> {
        MyStruct2 {
            version: &some_vec[0..2],
        }
    }
    
    struct MyStruct2<'a> {
        version: &'a [u8],
    }
    
    0 讨论(0)
提交回复
热议问题