文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
7.3 切片
切片(slice, [T]
)引用序列对象片段,无所有权。动态尺寸类型(DST, dynamically sized type),只能以 &[T]
存储或传递。
A type with a size that is known only at runtime is called a dynamically sized type (DST) or, informally, an unsized type. Slices and trait objects are two examples of DSTs.
let v = [1, 2, 3]; let s = v[..]; ^ doesn't have a size known at compile-time note: all local variables must have a statically known size
数组
[T; len]
vs&[T]
切片,因为[T]
长度在编译期无法确认,所以只能通过固定长度的 指针 定义。所谓&[T]
,是固定长度结构体的胖指针,存储指针和长度信息。
数据结构示意图:
&[T] +=====+ +=======//=======+ | ptr | ----------> | data ... | +-----+ +=======//=======+ | len | +=====+
struct &[T] { data_ptr: *mut T, length : usize, }
切片类型:
&[T]
: shared slice。&mut [T]
: mutable slice。Box<[T]>
: owned slice。
构造
从已有序列对象,以起始和结束索引进行构造。
[..]
:[0, len - 1]
[0..2]
:[0, 2)
[0..=2]
:[0, 2]
[3..]
:[3, len - 1]
[..3]
:[0, 3)
[..=3]
:[0, 3]
&v[..]
的实际操作是&(v[..])
。
fn main() { let v = vec![0, 1, 2, 3]; let s = &v[..]; // [0, 3] assert_eq!([0, 1, 2, 3], s); let s = &v[0..2]; // [0, 2) assert_eq!([0, 1], s); let s = &v[0..=2]; // [0, 2] assert_eq!([0, 1, 2], s); let s = &v[..2]; // [0, 2) assert_eq!([0, 1], s); let s = &v[..=2]; // [0, 2] assert_eq!([0, 1, 2], s); let s = &v[2..]; // [2, 3] assert_eq!([2, 3], s); }
注意区别数组引用和切片,虽然可以强制转换。
use std::convert::TryFrom; fn type_of<T>(_: &T) -> &'static str { std::any::type_name::<T>() } fn main() { let a = &[1, 2, 3]; let s = &a[..]; assert_eq!(type_of(&a), "&[i32; 3]"); // &array assert_eq!(type_of(&s), "&[i32]"); // &slice // --- convert ------- let s2: &[i32] = &[1, 2, 3]; // array -> slice let a2 = <&[i32; 3]>::try_from(s2).unwrap(); // slice -> array assert_eq!(type_of(&s), "&[i32]"); assert_eq!(type_of(&a2), "&[i32; 3]"); println!("{:?}", a2); // [1, 2, 3] }
操作
通过可变切片间接修改源数据。注意,切片索引与源数据索引未必一致。
fn main() { let mut v = vec![0, 1, 2, 3]; let s = &mut v[2..]; s[0] += 100; assert_eq!(v, [0, 1, 102, 3]); }
遍历(修改)切片。
fn main() { let s = &mut [1, 2, 3][..]; for x in s.iter_mut() { *x += 100; } for x in s.iter() { println!("{:?}", x); } println!("{:?}", s); }
可对切片进行重切(reslice)操作。
fn main() { let mut a = [1, 2, 3]; let s = &mut a[..]; let s2 = &mut s[1..]; s2[1] += 100; println!("{:?}", s); println!("{:?}", a); }
重新切片受目标切片限制,而非其底层数组。
fn main() { let mut a = [1, 2, 3, 4, 5, 6]; let s = &mut a[..3]; let s2 = &mut s[1..4]; ^ range end index 4 out of range for slice of length 3 }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论