Clone ——Semantic deep copy of data
1. What behavior does this Trait define?
pub trait Clone {
fn clone(&self) -> Self;
// 可选:更高效的克隆后赋值
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
Clone Defines a behavior:"Give me one &self, I return you an independent new value Self。"
Key semantic guarantees:
-
The returned value is the same as the original valuebehaviorally equivalent(
==Equality if the type implementsEq) -
The returned value is the same as the original valueMemory independent(Modifying one does not affect the other)
-
The value returned is given byThe caller owns(The caller is responsible for its life cycle)
Clone and Copy The fundamental difference:
Copy | Clone | |
|---|---|---|
| Calling method | Implicit (assignment and parameter passing occur automatically) | Explicit (must write .clone()) |
| what did | bit by bit copy (memcpy) | Any logic (including heap allocation, deep copy) |
| cost | Must be cheap (fixed bytes) | Can be cheap, can be expensive |
| Can it be customized | No (the compiler automatically copies bits) | Can (rewriteable clone()) |
| Relationship with Drop | mutually exclusive | compatible |
| can you control it | The compiler decides for you | You write code to control |
2. What is in C
2.1 Shallow copy = C default
C has no concept of "Clone". All types of assignments are bit-by-bit copies:
struct String {
char* data;
int len;
};
struct String s1;
s1.data = malloc(100);
strcpy(s1.data, "hello");
s1.len = 5;
struct String s2 = s1; // 浅拷贝:s2.data 与 s1.data 指向同一内存
// 现在 s1 和 s2 共享同一块堆内存 —— 谁释放?
2.2 Deep copy = differently named functions
There is no unified interface for deep copying in C, and each library uses different function names:
// 字符串:strdup —— 但只有 POSIX 有,C 标准没有
char* s = strdup("hello");
// 自定义结构体 —— 名字各有不同
struct string* string_dup(const struct string* s);
struct string* string_clone(const struct string* s);
struct string* string_copy(const struct string* s);
int string_copy_to(const struct string* src, struct string* dst);
// 标准库中也没有统一命名:
// bcopy (BSD), memcpy (C 标准), strcpy, strncpy, memmove...
// 每个函数名不同、参数顺序不同、边界条件不同
2.3 GLib’s reference-counted copy - GObject
Some C libraries try to solve the "need a copy but don't want a deep copy" problem through reference counting:
// GLib 中的例子
GObject* obj = g_object_new(...);
GObject* copy = g_object_ref(obj); // 递增引用计数
// 这不是"拷贝",这是"共享 + 计数"
// 调用者必须记得 g_object_unref(copy)
But even so, there is no unified interface:g_object_ref、g_strdup、g_array_copy- Each type has its own name.
3. Problem with C
3.1 There is no unified "copy" interface
This is the core question. In C, there is no standard way of writing "make a copy of this thing":
// 每次遇到一个新类型,你都要查文档:
struct image* copy = image_dup(original); // 这个库叫 dup
struct image* copy = image_clone(original); // 这个库叫 clone
struct image* copy = copy_image(original); // 这个库叫 copy
struct image* copy = image_copy(original); // 又一种叫法
// 甚至同一个库的不同版本:
// v1: image_copy(image, &result) → int
// v2: image_dup(image) → struct image*
This means:
-
You can't write a generic function that "copies a value of any type"
-
Every time you encounter a new type, you must learn its copy function name.
-
Unable to quickly identify "a copy was made here" during code review
3.2 The syntax of shallow copy and deep copy is the same
In C,The most dangerous things and the safest things use the same operator =:
// 下面两行代码的语法完全一样,但语义天差地别:
int a = 42;
int b = a; // ✅ 安全的:int 是值
struct String s = /* ... */;
struct String t = s; // ❌ 危险的:t.data 指向 s.data 的内存
// 语法上没有任何区别。只有你知道 String 内部有指针
// 代码审查中这种语句几乎不可能被注意到
3.3 Unable to express "this type is copyable" in generics
C does not have generics, but even if it did (e.g. _Generic), and cannot express "I need to make a deep copy of any type":
// C 的 _Generic 只能对有限类型列表做 dispatch
#define CLONE(x) _Generic((x), \
int: (x), \
char*: strdup(x), \
struct String: string_clone(&(x)) \
)
// 每个新类型都要手动添加 —— 库的使用者无法扩展
3.4 It is easy to misuse shallow copy and lead to resource management errors
struct User {
char* name;
int age;
};
void process_user(struct User u) { // 按值传参:浅拷贝
printf("%s", u.name);
// 函数结束后没人释放 u.name(原始 user 的 name 还存在)
}
void caller() {
struct User user;
user.name = malloc(100);
strcpy(user.name, "Alice");
user.age = 30;
process_user(user); // 浅拷贝整个 User —— 没问题,name 指针被复制了
free(user.name); // 释放堆内存
// 但如果 process_user 自己 free 了 u.name 呢?
// 约定:按值传参时接收方不释放,但纯靠约定。
}
There is no mechanism in C to ensure "lifetime safety of internal pointers when passing parameters by value".
4. Why does Rust need this trait?
4.1 Definition of Clone: Standard interface for semantic copying
Clone Provides aStandard and unified copy interface:
// 不管是什么类型,拷贝的写法都一样:
let copy = original.clone();
// ↑ 无论 original 是 String、Vec、HashMap 还是自定义类型
// 写法统一,语义统一:深拷贝、独立副本
// 泛型函数中:
fn duplicate<T: Clone>(x: &T) -> T {
x.clone() // 任何实现了 Clone 的类型都能拷贝
}
This is not possible in C - C does not have a standardized "copy" interface, let alone one that can be used in generics.
4.2 The complete relationship of Clone vs Copy
Copy yes Clone Sub-Trait:
pub trait Copy: Clone { }
This means:any Copy The type must also be Clone type. The converse is not true.
Clone(所有可自定义拷贝的)
│
├── Copy(隐式、位拷贝)
│ 如:i32, bool, f64, &T
│
└── 非 Copy 但 Clone 的类型(显式、可能昂贵)
如:String, Vec<T>, Box<T>, HashMap<K,V>
// Copy 类型 Clone 的实现 = 位拷贝(derive 自动生成)
let x: i32 = 42;
let y = x.clone(); // ✅ 可以,但没必要 —— Copy 类型隐式拷贝就够了
// 非 Copy 的 Clone 类型
let s = String::from("hello");
let t = s.clone(); // ✅ 深拷贝:新分配堆内存,复制字符串
// let t = s; // ❌ 这是 move,不是拷贝
4.3 Clone is an explicit cost tag
Seen in Rust code .clone(), you immediately know "there's a price here":
// 没有 .clone() —— 零成本操作
fn process(data: &Vec<i32>) {
for x in data.iter() { // 借用来遍历,没有拷贝
println!("{}", x);
}
}
// 有 .clone() —— 明确的代价标记
fn process_owned(data: &Vec<i32>) -> Vec<i32> {
data.clone() // 堆分配、拷贝所有元素
}
// 多个 .clone() —— 多个独立的拷贝
let v = vec![1, 2, 3];
let a = v.clone(); // 独立副本
let b = v.clone(); // 另一个独立副本
// 三次分配(v + a + b),三次独立
This is in sharp contrast to C: in C, expensive copies and cheap assignments use the same =, you can't judge the cost from the code.
clone() It is a grammatical mark of "copying occurred here". Scanning .clone() during code review can quickly locate all costly operations.
4.4 #[derive(Clone)] ——Automatically generated
Rust can automatically generate Clone Implementation of:
// 手动实现 —— 适用于需要自定义逻辑的场景
struct Custom {
data: Vec<i32>,
}
impl Clone for Custom {
fn clone(&self) -> Self {
Custom {
data: self.data.clone(),
// 如果有其他字段,逐一 clone
}
}
}
// 自动 derive —— 适用于"逐字段 clone 就行"的场景
#[derive(Clone)]
struct AutoCustom {
data: Vec<i32>,
name: String,
id: u64,
// 编译器自动为每个字段生成 self.field.clone() 的代码
}
#[derive(Clone)] All fields are required to be implemented Clone. If any field does not implement Clone, the compiler will report an error.
Contrast this with C: "manually writing copy functions" in C is the only path. Moreover, C's copy function has no compile-time check - if you forget to copy a field, the compiler will not report an error, but will only generate a silent bug.
// C 中手动写拷贝函数 —— 如果漏了字段,编译器沉默
struct Point {
int x;
int y;
// 后来加了 int z
};
struct Point point_clone(const struct Point* p) {
struct Point result;
result.x = p->x;
// ❌ 忘了复制 y —— 编译器不报错!
return result;
}
// Rust 中 derive —— 加字段后自动更新
#[derive(Clone)]
struct Point {
x: i32,
y: i32,
// 后来加了 z: i32 —— 编译器自动处理
}
4.5 clone_from ——Reuse existing resources
Clone trait takes an optional method clone_from:
let mut dst = String::from("world");
let src = String::from("hello");
// 普通写法:
dst = src.clone(); // 分配新内存,丢弃 dst 原有的内存
// 更高效的写法:
dst.clone_from(&src); // 重用 dst 的已有缓冲区,减少分配
clone_from The default implementation of *self = source.clone(), but types can override it for optimization. for String、Vec and other types,clone_from Will try to reuse existing heap allocations to avoid additional allocations and frees.
This is an optimization that is not possible in C - in C you cannot add a "more efficient copy" method without changing the interface. Or change the function name (string_copy_to(dst, src)), or change the agreement.
4.6 Clone is compatible with Drop
This is Clone and Copy An important difference:Realized Drop Types of Clone。
struct File {
fd: i32,
}
impl Drop for File {
fn drop(&mut self) {
close(self.fd); // 关闭文件描述符
}
}
impl Clone for File {
fn clone(&self) -> Self {
File { fd: dup(self.fd) } // ✅ 复制文件描述符
}
}
// 每次 clone 创建一个新的文件描述符
// 每个副本都有自己的 Drop —— 不会 double-close
Copy and Drop Mutually exclusive, because implicit bit copy + automatic destruction = double-free. but Clone is explicit and can be controlled by the type author clone() logic in - so it can be combined with Drop coexist.
4.7 Clone and generic programming
Clone Is one of the most commonly used trait bounds in the Rust standard library. Many generic function and type requirements T: Clone:
// Option<T> 的 clone
// 只有当 T: Clone 时,Option<T> 才实现 Clone
#[derive(Clone)]
enum Option<T> {
None,
Some(T),
}
// Vec<T> 的 clone
// 只有当 T: Clone 时,Vec<T> 才实现 Clone
impl<T: Clone> Clone for Vec<T> {
fn clone(&self) -> Self {
// 逐个元素 clone,分配到新 Vec 中
}
}
// 组合 clone 的实际效果:
let v = vec!["hello".to_string(), "world".to_string()];
let w = v.clone();
// ✅ 深拷贝整个 Vec:新分配两个 String 的堆内存
// v 和 w 完全独立
4.8 Zero-cost abstraction: Clone vs C manual copy
when Clone pass #[derive(Clone)] When generated and the type has only simple fields, the compilation result is exactly the same as the manual copy in C:
#[derive(Clone)]
struct Point {
x: f64,
y: f64,
z: f64,
}
let p2 = p1.clone();
// 编译后 = 三条 mov 指令(与 C 的 memcpy 完全一致)
// 没有任何额外的函数调用开销
but Clone Complex custom logic is also supported:
#[derive(Clone)]
struct SmartPointer<T> {
ptr: *mut T, // 裸指针
ref_count: usize, // 引用计数
}
// 不能直接 derive! 因为 *mut T 不是 Clone
// 需要手动实现:
impl<T> Clone for SmartPointer<T> {
fn clone(&self) -> Self {
// 递增引用计数,不拷贝底层数据
// 这是 Rc<T> 的实际逻辑
}
}
4.9 A comparison: copying from C string to Rust’s Clone
// C —— 三种不同的拷贝方式,三种不同的函数名
char* s1 = strdup("hello"); // POSIX
char s2[6]; strcpy(s2, "hello"); // 栈上
struct string* s3 = string_clone(s1); // 自定义库
// Rust —— 统一的 Clone 接口
let s1 = String::from("hello");
let s2 = s1.clone(); // 深拷贝
let s3 = s1.clone(); // 另一个深拷贝
// 甚至对不同类型,写法完全一致:
let v = vec![1, 2, 3].clone();
let m = HashMap::new().clone();
let custom = MyType::new().clone();
5. Dialogue with C Programmers
Dialogue 1: "C can also write deep copy functions"
C programmer: "I can also write deep copy functions in C. What is the difference between this and Rust's Clone?"
Rust: "The difference does not lie in whether it can be done, but in three points:"
1. Unified naming
// C —— 每次学一个新库,就要学它的拷贝函数名
char* strdup(const char*);
int obj_copy(struct obj* dst, const struct obj* src);
struct image* image_clone(const struct image*);
// Rust —— 永远是一个名字
let copy = original.clone();
2. Compiler involvement
#[derive(Clone)]
struct User {
name: String,
age: i32,
}
// 如果之后增加了 email: Email 字段
// 编译器自动为 email 生成 clone
// 不可能"漏掉一个字段"
// C —— 加字段后手动更新拷贝函数
// 如果忘了更新拷贝函数 —— 沉默的 bug
struct User user_clone(const struct User* u) {
struct User result;
result.name = strdup(u->name);
result.age = u->age;
// ❌ 加了 email 字段,这里忘了加 —— 编译器不报错
return result;
}
3. Generics can be constrained
fn clone_and_increment<T: Clone>(x: &T) -> (T, T) {
(x.clone(), x.clone()) // ✅ 泛型深度拷贝
}
// C 中无法写"拷贝任意类型"
// 只能为每个类型手写一个专用函数
Dialogue 2: "Clone is the generalization of strdup"
C programmer: "So Clone is the generic version of strdup?"
Rust: "Almost the same, but type-safe.
strduprightchar*Three things are done: determine the length, allocate memory, and copy characters.clone()Do the same thing for any type: determine size, allocate memory, copy data. The difference isstrdupOnly valid for C strings,clone()realized for anyCloneAll types are valid. "
// 对 C 程序员来说,Clone 泛化了 strdup 的概念
// strdup(char*) → char* (只对 C 字符串)
// .clone() → Self (对任何 Clone 类型)
6. Summary
6.1 Clone’s place in Rust’s type system
所有类型
│
├── Clone(可显式拷贝)
│ │
│ ├── Copy(可隐式拷贝)
│ │ 如:i32, bool, &T
│ │
│ └── 非 Copy + Clone(仅可显式拷贝)
│ 如:String, Vec, Box, HashMap
│
└── 非 Clone(不可拷贝)
如:MutexGuard, 自定义资源
6.2 Clone solves several core problems of C
| C's problem | Solution to Clone in Rust |
|---|---|
| There is no unified interface for deep copy | Unified for all types .clone() |
| Shallow copy has the same syntax as deep copy | =(move/implicit copy) vs .clone()(explicit deep copy) fully differentiated |
| Copy function may miss fields | #[derive(Clone)] Automatically process all fields |
| Can't use "copy" with generics | T: Clone as a generic constraint |
| Copy cost is opaque | .clone() is an explicit cost marker in the code |
| Resource type (with Drop) cannot be safely copied | Clone is compatible with Drop and can customize copy semantics |
| After adding fields, the copy function needs to be updated manually. | derive automatically adapts new fields |
6.3 Complete distinction between Clone and Copy
This is the key to understanding Rust's value semantics and resource semantics:
fn example(x: &T) {
let a = *x; // 如果 T: Copy → 隐式复制
// 如果 T: !Copy → 编译错误(不能移出引用)
let b = x.clone(); // 如果 T: Clone → 显式深拷贝
// 如果 T: !Clone → 编译错误
}
| Usage scenarios | use Copy | use Clone | Use move |
|---|---|---|---|
| When passing parameters to a function, the original value is still required | ✅ Implicit | ✅ Explicit .clone() | ❌ |
| Create an independent copy | ❌ Not applicable to resource types | ✅ .clone() | ❌ |
| No need to copy, transfer ownership | ❌ | ❌ | ✅Default behavior |
6.4 Changes in thinking of C programmers
// C 的思维:赋值 = 拷贝
struct String a = /* ... */;
struct String b = a; // "拷贝"——但只是浅拷贝
// Rust 的思维:
// let b = a;
// 如果 T: Copy → 隐式位拷贝
// 如果 T: !Copy → 移动所有权(不是拷贝)
// let b = a.clone();
// → 显式深拷贝
// → 代价在代码中可见
C you hit = As assignment and copy, in Rust = The default is move, and the copy must be made clear whether it is implicit (Copy) or explicit (Clone).
One sentence summary:C has only one kind of copy - bit-by-bit copy (
=/memcpy), unable to distinguish between shallow and deep copies, cheap and expensive. in RustCloneUnify all "customizable copies" into.clone()interface,#[derive(Clone)]Automatically generate implementation,T: CloneSupport for generic constraints - making C's confusing concept of "copy" part of the type system.
