移动与铁锈复制
比方说,我有这个结构
struct Triplet { one: i32, two: i32, three: i32, }  如果我把它传递给一个函数,它将被隐式复制 。 现在有时我读到有些值是不可复制的 ,因此不得不移动 。 我想知道,是否有可能使这个struct Triplet不可复制 ? 像实施一些额外的特点,告诉生锈,这将是不可复制的 ,因此必须移动 。 
 我到处读到,人们必须实现Clone特质才能复制那些不能隐式复制的东西,但是我从来没有读过其他方法,那就是隐式复制 ,使其不可复制 ,而不是复制 。 
这甚至有什么意义吗?
  前言 :这个答案是在select内置特性之前编写的,特别是Copy方面 – 已经实现。 我使用了块引用来表示只适用于旧scheme的部分(在提问时应用的部分)。 
旧 :要回答基本问题,可以添加一个存储
NoCopy值的标记字段。 例如struct Triplet { one: int, two: int, three: int, _marker: NoCopy }你也可以通过析构函数来实现(通过实现
Drop特性 ),但是如果析构函数什么都不做,那么使用标记types是首选。
 types现在默认移动,也就是说,当你定义一个新的types时,它不会实现Copy除非你明确地为你的types实现: 
 struct Triplet { one: i32, two: i32, three: i32 } impl Copy for Triplet {} // add this for copy, leave it out for move 
 只有在新的struct或enum包含的每个types都是自己的Copy才能实现该实现。 如果没有,编译器将打印一条错误消息。 它也可以只存在,如果types没有一个Drop实现。 
要回答你没有问的问题……“怎么了移动和复制?”:
首先我要定义两个不同的“副本”:
-  一个字节拷贝 ,它只是逐字节拷贝一个对象,不跟随指针,例如,如果你有(&usize, u64),在64位计算机上它是16个字节,浅拷贝将会把这些拷贝16字节并在其他一些16字节的内存块中复制它们的值, 而不触及&的另一端的usize。 也就是说,这相当于调用memcpy。
-  一个语义副本 ,复制一个值来创build一个新的(有些)独立的实例,可以安全地单独使用旧的实例。 例如,一个Rc<T>的语义拷贝只涉及增加引用计数,而一个Vec<T>的语义拷贝包括创build一个新的分配,然后将每个存储的元素从旧的语义复制到新的。 这些可以是深层复制(例如Vec<T>)或浅层(例如Rc<T>不接触存储的T),Clone被松散地定义为从内部语义复制typesT的值所需的最小量的工作a&TtoT
Rust就像C一样, 每个值的使用都是一个字节拷贝:
 let x: T = ...; let y: T = x; // byte copy fn foo(z: T) -> T { return z // byte copy } foo(y) // byte copy 
 无论T是否移动或是“隐式复制”,它们都是字节拷贝。  (要清楚的是,它们在运行时并不一定是逐字节拷贝:如果代码的行为被保留,编译器可以自由地优化拷贝。 
但是,字节拷贝存在一个基本的问题:最终会在内存中产生重复的值,如果它们具有析构函数,这可能是非常糟糕的,例如
 { let v: Vec<u8> = vec![1, 2, 3]; let w: Vec<u8> = v; } // destructors run here 
 如果w只是v的普通字节副本,那么将会有两个向量指向相同的分配,这两个向量都使用释放它的析构函数…导致一个double free ,这是一个问题。  NB。 如果我们把v的语义拷贝到w ,那么这将是完全正确的,因为那么w将是它自己的独立Vec<u8>并且析构函数不会相互践踏。 
这里有几个可能的修复:
- 让程序员像C一样处理它(C中没有析构函数,所以不会那么糟糕,只是留下了内存泄漏):P)
-  隐式执行一个语义副本,以便w具有自己的分配,就像带有其复制构造函数的C ++一样。
-  把价值的使用作为所有权的转移,使v不能再被使用,也不能使其析构者运行。
最后是Rust所做的事情: 移动只是源代码被静态无效的一个按值使用,所以编译器会阻止进一步使用现在无效的内存。
 let v: Vec<u8> = vec![1, 2, 3]; let w: Vec<u8> = v; println!("{}", v); // error: use of moved value 
因为他们有一些资源的pipe理/所有权(例如内存分配或文件句柄),并且字节拷贝不太可能正确地复制这个值,所以具有析构函数的types必须在使用值时移动(也就是当字节复制时)所有权。
“那么…什么是隐含的副本?”
 考虑一下像u8这样的基本types:一个字节拷贝很简单,就是复制单个字节,而一个语义拷贝就是一样简单,拷贝一个字节。 特别是,一个字节拷贝是一个语义拷贝… Rust甚至有一个内置的特征Copy ,捕获哪些types具有相同的语义和字节拷贝。 
 因此,对于这些Copytypes,按值使用也是自动语义副本,所以继续使用源是完全安全的。 
 let v: u8 = 1; let w: u8 = v; println!("{}", v); // perfectly fine 
Old :
NoCopy标记覆盖了编译器的自动行为,假定可以是Copytypes(即只包含原语和&聚合)是Copy。 但是,如果select内置特征,这将会改变。
 如上所述,select性内置特征被实现,所以编译器不再具有自动行为。 但是,过去用于自动行为的规则与检查Copy是否合法相同。 
最简单的方法是embedded你的types不可复制的东西。
标准库为这个用例提供了一个“标记types”: NoCopy 。 例如:
 struct Triplet { one: i32, two: i32, three: i32, nocopy: NoCopy, }