向量元素的转移

不是所有的值都能转移,比如向量的元素,因为转移之后这个元素的位置就成了未初始化的状态,而编译器又不能确定这个索引将来还会不会用。如果想要转移就要指明该位置要怎么处理,比如用popswap_removestd::mem::replace这样的方法。
for ... in v语句会吧向量v里的元素转移,便利之后整个v变成未初始化的状态,所以不用担心上面的问题。
也可以将元素换成一些有状态的数据类型,比如Option,把原数据取出换成None放回去。

  1. let mut composers = Vec::new();
  2. composers.push(
  3. Some("Palestrina".to_string()),
  4. );
  5. let first_name = std::mem::replace(&mut composers[0], None);
  6. // 甚至Option有专门的方法来支持这种操作
  7. // let first_name = composers[0].take();
  8. assert_eq!(first_name, Some("Palestrina".to_string()));
  9. assert_eq!(composers[0], None);

向量元素的复制

上面的的操作之所以是转移是因为,向量的元素是有可能使用较多内存的(也就是内存可变的?也就是指针指向一个buffer的类型?)。
如果元素本身是简单的数据类型,比如整型、浮点、布尔,那转移所有权是没有意义的,以为转移所有权本身也要把指针复制给另一个变量,基本类型本身也就是复制一个值。所以简单类型使用的是复制而不是转移。

会被复制而不是转移的类型都是Copy类型,标准的Copy类型包括:整型,浮点数,char,bool,元素是Copy类型的元组和数组。而那些drop的时候需要做特殊处理的都不是Copy。
自定义的结构体和枚举类型默认都不是Copy。但如果结构体中的字段都是Copy类型的,则可以给结构体加属性#[derive(Copy, Clone)]让他变成Copy的。
但不要轻易将自定义类型设置成Copy的。因为将来一旦类型有改成需要使用复杂类型的化,原来的代码可能都需要做修改。

计数指针(Rc,Arc)

Rc的引用简单的说都是不可变引用