gpt4 book ai didi

rust - 无法将字符串拆分为具有显式生命周期的字符串切片,因为该字符串的生命周期不够长

转载 作者:行者123 更新时间:2023-11-29 08:22:49 28 4
gpt4 key购买 nike

我正在写一个库,它应该从实现 BufRead 的东西中读取特征;网络数据流、标准输入等。第一个函数应该从该读取器读取数据单元并返回一个填充的结构,其中大部分填充了 &'a str。从线路中的帧解析的值。

这是一个最小版本:

mod mymod {
use std::io::prelude::*;
use std::io;

pub fn parse_frame<'a, T>(mut reader: T)
where
T: BufRead,
{
for line in reader.by_ref().lines() {
let line = line.expect("reading header line");
if line.len() == 0 {
// got empty line; done with header
break;
}
// split line
let splitted = line.splitn(2, ':');
let line_parts: Vec<&'a str> = splitted.collect();

println!("{} has value {}", line_parts[0], line_parts[1]);
}
// more reads down here, therefore the reader.by_ref() above
// (otherwise: use of moved value).
}
}

use std::io;

fn main() {
let stdin = io::stdin();
let locked = stdin.lock();
mymod::parse_frame(locked);
}

在尝试不同的解决方案后出现了一个我无法修复的错误:

error: `line` does not live long enough
--> src/main.rs:16:28
|
16 | let splitted = line.splitn(2, ':');
| ^^^^ does not live long enough
...
20 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the body at 8:4...
--> src/main.rs:8:5
|
8 | / {
9 | | for line in reader.by_ref().lines() {
10 | | let line = line.expect("reading header line");
11 | | if line.len() == 0 {
... |
22 | | // (otherwise: use of moved value).
23 | | }
| |_____^

生命周期'a因为 &str 是在结构和数据管理器结构的实现上定义的需要明确的生命周期。这些代码部分作为最小示例的一部分被删除。

BufReader有一个 lines()返回 Result<String, Err> 的方法.我使用 expect 处理错误或 match从而解压 Result这样程序现在就有了裸String .然后将多次执行此操作以填充数据结构。

许多答案都说 unwrap结果需要绑定(bind)到一个变量,否则它会丢失,因为它是一个临时值。但是我已经保存了解压的 Result变量中的值 line我仍然收到错误。

  1. 如何修复此错误 - 尝试数小时后仍无法正常工作。

  2. &str 做所有这些生命周期声明是否有意义?在数据管理员结构中?这将主要是一个只读数据结构,最多替换整个字段值。 String也可以使用,但发现文章说 String性能低于 &str - 并且此帧解析器函数将被调用多次并且对性能至关重要。

Stack Overflow 上存在类似的问题,但没有一个能完全回答这里的情况。

为了完整性和更好的理解,以下是完整源代码的摘录,说明为什么会出现生命周期问题:

数据结构声明:

// tuple
pub struct Header<'a>(pub &'a str, pub &'a str);

pub struct Frame<'a> {
pub frameType: String,
pub bodyType: &'a str,
pub port: &'a str,
pub headers: Vec<Header<'a>>,
pub body: Vec<u8>,
}

impl<'a> Frame<'a> {
pub fn marshal(&'a self) {
//TODO
println!("marshal!");
}
}

完整的函数定义:

pub fn parse_frame<'a, T>(mut reader: T) -> Result<Frame<'a>, io::Error> where T: BufRead {

最佳答案

你的问题可以简化为:

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

您创建一个 String在你的函数中,然后声明对该字符串的引用保证在整个生命周期内存在'a .可惜一生'a 不在你的控制之下——函数的调用者可以选择生命周期。这就是通用参数的工作原理!

如果函数的调用者指定了 'static 会发生什么生命周期?您的代码在运行时分配一个值,怎么可能保证该值甚至比 main 的生命周期更长?功能?不可能,这就是编译器报错的原因。

一旦你获得了更多的经验,函数签名 fn foo<'a>()会像红色警报一样跳到您面前 — 有一个未使用 的通用参数。这很可能意味着坏消息。


return a populated struct filled mostly with &'a str

你不可能用你当前的代码组织来做到这一点。引用必须指向某物。您没有为指向的值提供生存的任何地方。你不能 return an allocated String as a string slice .

在你跳到它之前,没有你cannot store a value and a reference to that value in the same struct .

相反,您需要拆分创建 String 的代码以及解析 &str 的那个并返回更多 &str引用。这就是所有现有的零拷贝解析器的工作方式。您可以查看这些以获取灵感。

String has lower performance than &str

不,它真的没有。创造大量无关的String当然,s 是一个坏主意,就像在任何语言中分配太多都是一个坏主意一样。

关于rust - 无法将字符串拆分为具有显式生命周期的字符串切片,因为该字符串的生命周期不够长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44641830/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com