fn main(){ let s2 = test(); println!("s2={}",s2 ); } fn test() -> String{ let s1 = String::from("test1"); return s1 }
打印出 s2=test1
这里有一个疑问,s1 对应的内存有没有被销毁? return s1 这时作用域已完成,不是因销毁 s1 吗,那返回到 main 里的是什么? “test1"这 string 是否于内存中复制过?
1 luman 2024-01-15 14:38:37 +08:00 ![]() s1 的所有权给 s2 了 |
![]() | 2 sleeepyy 2024-01-15 14:46:14 +08:00 ![]() 没有销毁,return 的时候把所有权给 s2 了 |
![]() | 3 yelog 2024-01-15 14:55:58 +08:00 ![]() 上面两位老哥说的很好, 我补充一下官网原文关于这块的描述和示例, 可以尝试理解一下 https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#return-values-and-scope |
![]() | 4 ch3nOr 2024-01-15 15:11:07 +08:00 ![]() 修改了一下楼主的程序,打印了一下内存地址,发现在 test 内 move 内存地址也会发生改变,move 到外部也会 https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=fcfb04f8f33db75f1934513021102b30 |
![]() | 5 dxatgp02 OP |
![]() | &nbs; 6 detached 2024-01-15 16:32:54 +08:00 ![]() @ch3nOr 这个是符合预期的,"test1"这个字符串所在的内存并没有发生变化。而每一个 variable(s1,s2,s3)都是一个新的,他们均指向这个字符串。 |
![]() | 7 ch3nOr 2024-01-15 17:09:11 +08:00 ![]() @detached 验证了一下,确实是这样的: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8e72d327ee3e3379797b5b156f034ad3 上面 #4 的程序打印的是 s1 、s2 、s3 的地址 |
8 docxs 2024-01-15 17:26:37 +08:00 via iPhone ![]() 你对比理解成 cpp 的 move ,就好理解了 |
![]() | 9 araraloren 2024-01-17 10:03:21 +08:00 ![]() It transfer the ownership of s1 to s2(move is bitwise copy, but not call the drop of `s1`). And `s2` will be dropped when out of scope of main. |
![]() | 10 buxudashi 2024-01-21 15:15:38 +08:00 ![]() 你认为的消毁是什么? 把全部内存段内的位变成 0 ? 事实上的销毁是。你不管里面的数据是什么。你不取值不引用它的索引就算销了。 |
11 Terry166 2024-03-29 18:43:33 +08:00 String 是一个可变的,堆上分配的 UTF-8 的字节缓冲区,它是可增长的、可变的、有所有权的、UTF-8 编码的字符串类型,使用 to_string 或者 String::from 创建。 fn test() -> String{ let s1 = String::from("test1"); return s1 } // 创建并返回一个具有所有权的字符串, let s2 = test(); // 把所有权转移给 s2 ,s1 就失效了。 内存表示如下: [ s1 ] [s2 ] // 栈上的胖指针(包含三个字:地址,容量,大小) +++++++ stack frame │ │ │ │ │ 8 │ 5 │ ++++ │+++│ │ │ ++ │ +V++++++++ heap │ t │ e │ s │ t │ 1 │ l │ │ │ // 保存在堆上的数据 +++++++++ |