# Rust 所有权 vs C++ 智能指针

## 核心区别

| 维度 | Rust 所有权 | C++ 智能指针 |
|------|----------|----------|
| **检查时机** | 编译时强制 | 运行时执行 |
| **违规后果** | 编译失败 | 内存泄漏/悬垂指针 |
| **学习曲线** | 陡峭（前置约束） | 平缓（后置修复） |

## 本质差异

### 1. **强制性 vs 可选性**
```rust
// Rust：编译器强制执行
let s = String::from("hello");
let s2 = s;  // s 所有权转移
println!("{}", s);  // ❌ 编译错误，s 已失效
```

```cpp
// C++：程序员自觉遵守
std::unique_ptr<std::string> s = std::make_unique<std::string>("hello");
auto s2 = std::move(s);
std::cout << *s;  // ⚠️ 运行时未定义行为（程序员责任）
```

### 2. **所有权规则 vs 引用计数**
```rust
// Rust：一个值只有一个所有者
let x = vec![1, 2, 3];
let y = x;  // 所有权转移，x 失效
// 栈上只有 y 指向堆数据
```

```cpp
// C++：shared_ptr 允许多个所有者
auto x = std::make_shared<std::vector<int>>({1, 2, 3});
auto y = x;  // 引用计数 +1，两个都有效
// 运行时计数：当最后一个指针销毁时才释放
```

### 3. **借用 vs 指针**
```rust
// Rust：借用是编译时概念，无运行时成本
fn borrow(s: &String) { }  // 不转移所有权
let s = String::from("hello");
borrow(&s);
println!("{}", s);  // ✅ 仍然有效
```

```cpp
// C++：必须用指针/引用，但无编译时保证
void borrow(const std::string* s) { }
std::string s = "hello";
borrow(&s);
std::cout << s;  // 依赖程序员不会在函数内 delete
```

## 实际影响

| 场景 | Rust | C++ |
|------|------|-----|
| **内存泄漏** | 不可能（除非 unsafe）| 容易发生 |
| **悬垂指针** | 不可能 | 容易发生 |
| **性能** | 零成本抽象 | shared_ptr 有引用计数开销 |
| **灵活性** | 受限（必须满足规则）| 高（但需自律） |

## 打个比喻

- **Rust 所有权**：法律禁止（编译器执行）
- **C++ 智能指针**：道德规范（程序员遵守）

Rust 把内存安全从"最佳实践"变成了"语法强制"。