< 返回版块

github.com/shanliu/lsys 发表于 2023-08-04 14:57

struct AA<'t> {
    kk: Vec<&'t str>,
    //......
}
fn new<'t>(dd: String) -> AA<'t> {
    //dd 是非常大的字符串
    //不能改为&'str
    //期望:希望返回AA这个结构
    //因为如果把kk改为 Vec<String>,内存可能翻几倍
    //所以希望Vec<&'t str> 为对dd字符串引用,该如何实现
    todo!()
}

评论区

写评论
苦瓜小仔 2023-08-06 18:57

随意揣测就有意义了吗?

就算我粘贴了又怎么样?(我没那么无聊去准备一个本子记录这些东西)

何况这种帖子里“无意义”的问题全部源自于对生命周期不了解,这是事实。

你要是观察地更仔细一些,官方论坛我出现的身影可比在这里多地多,那里我也重复回答很多类似的问题,是不是又要猜测我准备了另一个英文本子做应对 :)

--
👇
zylthinking: 你看看他的其他帖子, 你会发现类似

准备好接受生命周期的考验了吗?你对生命周期有多熟

这样的车轱辘话不停的出现, 然而这除了显得他像个导师外, 并没有其他半毛钱意义。

你若是观察的更仔细些, 就会发现其实前几次和这次连标点符合都不带差的,我有点好奇是不是他将这句话保存到一个小本子上, 用的时候直接粘贴出来。

zylthinking 2023-08-06 09:30

你看看他的其他帖子, 你会发现类似

准备好接受生命周期的考验了吗?你对生命周期有多熟

这样的车轱辘话不停的出现, 然而这除了显得他像个导师外, 并没有其他半毛钱意义。

你若是观察的更仔细些, 就会发现其实前几次和这次连标点符合都不带差的,我有点好奇是不是他将这句话保存到一个小本子上, 用的时候直接粘贴出来。

--
👇
Pikachu: 另外我不理解苦瓜上面哪里说教了。

本身你在提一个不可能的问题:想要虚空创造一个lifetime。既然都是写了好几年rust了,这种问题应该有敏感性,出现这种问题就得改设计绕开了。

苦瓜的回复里面已经解释了为什么不可能,以及有哪些设计可以绕开这个问题。除了对应于那个英文贴回复中的“索引”,还多给了几种解决方案。

zylthinking 2023-08-06 09:16

我都没看明白问题, 追着链接到 user form 下也没瞅明白。 为啥我自认为 into_boxed_str 然后 leak 的办法就没人看一眼呢, 我觉得应该符合需求吧, 虽然需要自己管理内存了, 不那么 rust, 但明显比啥自引用的看上去直观啊

作者 github.com/shanliu/lsys 2023-08-05 19:44

内存增加几倍到多大?你有基准测试过吗?这是性能瓶颈吗?

我没那么无聊,我更愿意传所有权,如果不是发现内存使用暴涨的情况的话。

准备好接受生命周期的考验了吗?你对生命周期有多熟?

这东西也算都理解吧。

想要虚空创造一个lifetime

只是尝试寻找一个更优的结构。没说一定要凭空创造一个lifetime,比如 Vec<std::ops::Range<usize>>, 解决问题就行。

有问题就提出来讨论下嘛。能讨论就讨论,不能讨论就算呗。

--
👇
Pikachu: 另外我不理解苦瓜上面哪里说教了。

本身你在提一个不可能的问题:想要虚空创造一个lifetime。既然都是写了好几年rust了,这种问题应该有敏感性,出现这种问题就得改设计绕开了。

苦瓜的回复里面已经解释了为什么不可能,以及有哪些设计可以绕开这个问题。除了对应于那个英文贴回复中的“索引”,还多给了几种解决方案。

Pikachu 2023-08-05 00:17

另外我不理解苦瓜上面哪里说教了。

本身你在提一个不可能的问题:想要虚空创造一个lifetime。既然都是写了好几年rust了,这种问题应该有敏感性,出现这种问题就得改设计绕开了。

苦瓜的回复里面已经解释了为什么不可能,以及有哪些设计可以绕开这个问题。除了对应于那个英文贴回复中的“索引”,还多给了几种解决方案。

Pikachu 2023-08-05 00:05

做不到。

我的上一个回复和那个英文贴里面都说了,几乎不可能实现一个函数,使得其参数不带有生命周期,而返回值却带有生命周期。(不考虑lifetime elision这种语法糖。)

这种时候解决方案有两种:

  1. 英文贴中的存index range的方案,代价是额外的边界检查。你需要自己确保string不会被后续修改。
  2. 老老实实写&str。不想把string向外传递,那就把要执行的函数传进来。
fn apply<T>(x: impl ToDD, f: impl FnOnce(AA) -> T) -> T {
    let x_string = x.create_dd();
    let aa = AA::new(&x_string);
    f(aa)
}

(以上代码我还没尝试编译,但应该不会有大问题。)

作者 github.com/shanliu/lsys 2023-08-04 20:34

我知道最简单方法就是把引用向外传导,但这不是我想要的结果。 所以,才先把不能改为&'str的限制加上。

--
👇
Pikachu: 除非你用unsafe和transmute,不然你很难虚空生成一个生命周期。返回值的生命周期一般是跟某个/某些参数的生命周期联系在一起的。

你这里参数拿了dd的ownership,所以String在函数末尾就会被析构,然后返回的东西全都是悬垂指针。

最简单的解法就是把参数改成&str,但被你提前否定了。所以这里需要你详细解释一下,问题描述中

dd 是非常大的字符串,不能改为&'str

这句话在我看来没有明确的因果关系,需要补充更多的上下文信息。

另外楼上那个产生了自引用结构,大概率是过不了编译的。

作者 github.com/shanliu/lsys 2023-08-04 20:31
//比如定义个trait 来提供数据
trait ToDD {
    fn create_dd(&self) -> String;//提供适配器返回所有权的变量,往往实现者会比较容易处理
}
....
impl <'t>AA<'t>{

fn new(dd_from: impl ToDD) -> Self {
   //这里传实现ToDD的实例
    let ss=dd_from. create_dd();
//提前对字符串ss进行分析,并做些标注,也可以存位置或直接clone一份
//只是当ss太大,clone方式不太好,存位置方式不方便写。
   Self{ss:ss,ccc...}
}
}

--
👇
Pikachu: 除非你用unsafe和transmute,不然你很难虚空生成一个生命周期。返回值的生命周期一般是跟某个/某些参数的生命周期联系在一起的。

你这里参数拿了dd的ownership,所以String在函数末尾就会被析构,然后返回的东西全都是悬垂指针。

最简单的解法就是把参数改成&str,但被你提前否定了。所以这里需要你详细解释一下,问题描述中

dd 是非常大的字符串,不能改为&'str

这句话在我看来没有明确的因果关系,需要补充更多的上下文信息。

另外楼上那个产生了自引用结构,大概率是过不了编译的。

作者 github.com/shanliu/lsys 2023-08-04 20:21

不要动不动就说教,学了几年谁还不知道你说的这个东西。。。。 我就是在尝试找一个出现类似自引用场景的时候,除了向外传到引用外有没其他的更友好的解决方案。

国内的rust圈搞的乌烟瘴气的,老外好歹在提供解决的方式,比如他说的

kk: Vec<std::ops::Range<usize>>,

有问题尝试解决问题不就好了,哎,不过也先表示感谢回复。国内基本rust圈都好像死水一般沉静了。

--
👇
苦瓜小仔: 发布交叉贴需附上链接:https://users.rust-lang.org/t/help-problems-with-field-ref-in-struct/97981

dd 是非常大的字符串,不能改为&'str;期望:希望返回AA这个结构

数据的所有者和引用数据的结构分开,是 Rust 最基础的设计结构。你的数据一定会存在某处,而 fn new<'t>(dd: String) -> AA<'t> 移动 String 的所有权来返回悬垂引用是完全不可能的,因为它在函数返回时销毁,无法构建 AA。

(清醒一点,引用不是这样用的!!!)

通过 fn new<'t>(dd: &'t str) -> AA<'t> 构建 AA,这是最基本的做法,而你并没有提供理由来表明为什么不能改成它。

因为如果把kk改为 Vec,内存可能翻几倍

内存增加几倍到多大?你有基准测试过吗?这是性能瓶颈吗?

潜在的替代做法:

  1. 共享所有权:Rc/Arc/...+ 索引
  2. 块分配(批量分配+批量销毁): Arena
  3. string interning
  4. 自引用

希望Vec<&'t str> 为对dd字符串引用

准备好接受生命周期的考验了吗?你对生命周期有多熟?

引用结构的核心功能是作为临时数据结构来使用,长链条传递引用通常是不正确地使用引用。

zylthinking 2023-08-04 16:46

走这条路: String::into_boxed_str ===> Box::leak() 不用了自己释放内存

苦瓜小仔 2023-08-04 16:15

发布交叉贴需附上链接:https://users.rust-lang.org/t/help-problems-with-field-ref-in-struct/97981

dd 是非常大的字符串,不能改为&'str;期望:希望返回AA这个结构

数据的所有者和引用数据的结构分开,是 Rust 最基础的设计结构。你的数据一定会存在某处,而 fn new<'t>(dd: String) -> AA<'t> 移动 String 的所有权来返回悬垂引用是完全不可能的,因为它在函数返回时销毁,无法构建 AA。

(清醒一点,引用不是这样用的!!!)

通过 fn new<'t>(dd: &'t str) -> AA<'t> 构建 AA,这是最基本的做法,而你并没有提供理由来表明为什么不能改成它。

因为如果把kk改为 Vec,内存可能翻几倍

内存增加几倍到多大?你有基准测试过吗?这是性能瓶颈吗?

潜在的替代做法:

  1. 共享所有权:Rc/Arc/...+ 索引
  2. 块分配(批量分配+批量销毁): Arena
  3. string interning
  4. 自引用

希望Vec<&'t str> 为对dd字符串引用

准备好接受生命周期的考验了吗?你对生命周期有多熟?

引用结构的核心功能是作为临时数据结构来使用,长链条传递引用通常是不正确地使用引用。

Pikachu 2023-08-04 16:01

除非你用unsafe和transmute,不然你很难虚空生成一个生命周期。返回值的生命周期一般是跟某个/某些参数的生命周期联系在一起的。

你这里参数拿了dd的ownership,所以String在函数末尾就会被析构,然后返回的东西全都是悬垂指针。

最简单的解法就是把参数改成&str,但被你提前否定了。所以这里需要你详细解释一下,问题描述中

dd 是非常大的字符串,不能改为&'str

这句话在我看来没有明确的因果关系,需要补充更多的上下文信息。

另外楼上那个产生了自引用结构,大概率是过不了编译的。

DDD 2023-08-04 15:26

struct StringCutter<'t> { kk: Vec<&'t str>, origin_string: String, }

1 共 13 条评论, 1 页