为何字符串字面量未发生移动?Rust移动语义代码疑问
解答:为什么移除
&后程序依然正常运行? 这个问题核心是混淆了字符串字面量的类型和Rust的引用传递规则,我来一步步给你拆解清楚:
- 首先明确
s2的实际类型:你写的let s2 = "bar";里,s2并不是拥有所有权的String,而是&'static str——一个指向程序静态内存区域的字符串切片引用,这个字符串是编译时就嵌入到二进制里的,生命周期贯穿整个程序。 - 再看
push_str的方法要求:String::push_str的签名是pub fn push_str(&mut self, string: &str),它的参数本身就需要一个&str类型的引用。 - 原来的代码中
s1.push_str(&s2),其实你是对一个&str再取了一次引用,得到的是&&str,但Rust的**自动解引用(Deref coercion)**特性会自动把&&str转换成&str,所以代码能正常工作,但这其实是多此一举的操作。 - 当你改成
s1.push_str(s2)时,你直接传递的就是s2本身(&str类型),完全匹配push_str的参数要求。这里根本不会触发“移动”,因为&str作为不可变引用类型,它实现了Copytrait——传递的时候只是复制了这个引用(本质就是复制了一个指向静态内存中"bar"的指针),原来的s2完全不受影响,所以后续的println!("s2 is {}", s2);自然能正常运行。
你之所以会产生“应该触发移动”的误解,大概率是把String和&str搞混了:如果s2是String类型(比如let s2 = String::from("bar");),那直接调用s1.push_str(s2)就会报错——因为String没有实现Copy,直接传递会触发所有权移动,后续就无法再使用s2了。
内容的提问来源于stack exchange,提问作者Kajal Sinha
相关产品推荐
相关产品推荐

