Rust中.to_owned()、.clone()与解引用(*)的差异探究
Rust中
to_owned()、clone()和解引用*对数组切片的克隆差异 先看你的代码和输出:
fn main() { let a = &[1, 2, 3]; let mut o = a.to_owned(); let mut c = a.clone(); let mut d = *a; o[0] = 7; c[0] = 8; d[0] = 9; println!("o: {:?}", o); println!("c: {:?}", c); println!("d: {:?}", d); println!("a: {:?}", a); }
输出:
o: [7, 2, 3] c: [8, 2, 3] d: [9, 2, 3] a: [1, 2, 3]
三者表面上都复制了a的内容,但类型和内存分配逻辑完全不同:
1. a.to_owned() → Vec<i32>
to_owned()是ToOwned trait的方法,这里a会被自动强制转换为切片&[i32],对应的实现会在堆上分配内存,把切片元素复制进去,返回一个动态增长的Vec<i32>。
- 特点:可以随时调用
push/pop调整长度,内存分配在堆上,生命周期由所有权系统管理。
2. a.clone() → [i32; 3]
Rust方法调用会自动解引用,所以a.clone()等价于(*a).clone()。a的实际类型是&[i32; 3](固定大小数组的引用),而[i32; 3]实现了Clone trait,克隆后返回一个栈分配的固定大小数组。
- 特点:长度固定,无法动态增减元素,内存分配在栈上,性能更高但受栈大小限制。
3. *a → [i32; 3]
直接解引用a会得到底层的固定大小数组[i32; 3],因为i32实现了Copy trait,数组也自动实现Copy,所以这是一次值拷贝。
- 特点:和
clone()的结果类型完全一致,都是栈上的固定大小数组,本质是直接复制值,无需调用clone方法,更简洁。
直观验证差异的例子
给o(向量)添加元素是合法的:
o.push(4); // 正常运行,o变为[7,2,3,4]
但给c或d(固定数组)添加元素会直接编译错误:
c.push(4); // 编译错误:数组没有`push`方法
打印类型也能直观看到区别:
println!("o的类型:{}", std::any::type_name::<_>(&o)); // Vec<i32> println!("c的类型:{}", std::any::type_name::<_>(&c)); // [i32; 3] println!("d的类型:{}", std::any::type_name::<_>(&d)); // [i32; 3]
内容的提问来源于stack exchange,提问作者fadedbee
相关产品推荐
相关产品推荐

