Rust中字符串传入元组的所有权转移问题及相关代码编译疑问
Rust中字符串传入元组的所有权转移问题及相关代码编译疑问
嘿,我来帮你理清这个Rust所有权的问题~其实这和你的Rust版本没关系,核心是Rust的所有权规则和元组元素的求值顺序在起作用,咱们一步步拆解:
首先看你能正常编译的这段代码:
fn return_two_value(str: String) -> (String, usize) { let len = str.len(); (str, len) }
这里你先通过str.len()获取了字符串的长度并存在len变量里,这时候str的所有权还没发生转移,是完全有效的。之后把str放进元组,所有权转移到元组中,但因为len已经提前存好了,后续不需要再用到str,所以编译器完全没问题。
再看你说无法编译的简化版本:
fn return_two_value(str: String) -> (String, usize) { (str, str.len()) }
问题出在Rust对元组元素的求值顺序是从左到右的!当你构造这个元组时,编译器会先处理第一个元素str,这时候str的所有权已经被转移到元组里了——也就是说,原来的str变量已经变成了“无效”状态,不能再被使用。但紧接着你又调用了str.len(),这时候你试图访问一个已经被移动的变量,自然会触发编译器的所有权错误。
而你调整顺序后的代码能正常编译,也正是因为求值顺序的原因:
fn return_two_value_(str: String) -> (usize, String) { (str.len(), str) }
这次编译器先处理第一个元素str.len(),此时str还没被移动,完全可以正常调用方法获取长度;处理完第一个元素后,再把str移动到元组的第二个位置,这时候所有权转移是合法的,因为之前已经完成了对str的所有读取操作。
至于AI告诉你(str, str.len())可行,应该是它没考虑到Rust严格的所有权规则和求值顺序的交互,这个结论是错误的哦。
备注:内容来源于stack exchange,提问作者haoduoduo
相关产品推荐
相关产品推荐

