Carbon内存管理 #
一、内存管理概述 #
Carbon采用现代化的内存管理策略,结合手动管理和所有权系统,在保持性能的同时提高内存安全性。
二、指针 #
2.1 原始指针 #
carbon
var x: i32 = 42;
var p: i32* = &x;
Print("值: {0}", *p); // 42
*p = 100;
Print("x = {0}", x); // 100
2.2 空指针 #
carbon
var p: i32* = nullptr;
if (p != nullptr) {
Print("{0}", *p);
} else {
Print("空指针");
}
2.3 指针运算 #
carbon
var arr: [i32; 5] = (1, 2, 3, 4, 5);
var p: i32* = &arr[0];
Print("{0}", *p); // 1
Print("{0}", *(p + 1)); // 2
Print("{0}", *(p + 2)); // 3
三、引用 #
3.1 引用基础 #
carbon
var x: i32 = 42;
var ref: i32& = x;
ref = 100;
Print("x = {0}", x); // 100
3.2 引用与指针的区别 #
carbon
var x: i32 = 42;
// 引用:必须初始化,不能为空,不能重新绑定
var ref: i32& = x;
// 指针:可以为空,可以重新指向
var ptr: i32* = &x;
ptr = nullptr;
3.3 常量引用 #
carbon
fn PrintValue(ref: const i32&) {
Print("{0}", ref);
// ref = 100; // 错误:不能修改常量引用
}
var x: i32 = 42;
PrintValue(x);
四、所有权系统 #
4.1 所有权概念 #
Carbon引入所有权系统来管理资源:
carbon
// 所有权转移
var s1: String = "Hello";
var s2: String = s1; // s1的所有权转移给s2
// s1 不再有效
Print("{0}", s2); // Hello
// Print("{0}", s1); // 错误:s1已失效
4.2 借用 #
carbon
fn Length(s: String&) -> i32 {
return s.Length();
}
var s: String = "Hello";
var len: i32 = Length(s); // 借用s
Print("{0}", s); // s仍然有效
4.3 可变借用 #
carbon
fn Append(s: String&, suffix: String) {
s += suffix;
}
var s: String = "Hello";
Append(s, " World");
Print("{0}", s); // Hello World
4.4 借用规则 #
carbon
fn Example() {
var s: String = "Hello";
// 规则1:可以有多个不可变借用
var r1: String& = s;
var r2: String& = s; // OK
// 规则2:只能有一个可变借用
var m1: String& = s;
// var m2: String& = s; // 错误:已有可变借用
// 规则3:不可变借用和可变借用不能同时存在
// Print("{0}", r1); // 错误:有可变借用时不能使用不可变借用
}
五、堆内存 #
5.1 动态分配 #
carbon
// 使用New分配堆内存
var p: i32* = New(i32);
*p = 42;
Delete(p);
// 数组分配
var arr: i32* = New(i32[10]);
for (i in 0..10) {
arr[i] = i;
}
Delete(arr);
5.2 智能指针 #
carbon
// UniquePtr:独占所有权
var ptr: UniquePtr(i32) = MakeUnique(42);
Print("{0}", *ptr);
// SharedPtr:共享所有权
var shared: SharedPtr(i32) = MakeShared(42);
var shared2: SharedPtr(i32) = shared;
Print("{0}", *shared2);
5.3 自动释放 #
carbon
fn Example() {
var ptr: UniquePtr(i32) = MakeUnique(42);
// 使用ptr
Print("{0}", *ptr);
// 函数结束时自动释放
}
六、内存安全 #
6.1 空指针检查 #
carbon
fn SafeAccess(p: i32*) -> Optional(i32) {
if (p == nullptr) {
return None;
}
return Some(*p);
}
var p: i32* = nullptr;
match (SafeAccess(p)) {
case Some(v) => Print("{0}", v);
case None => Print("空指针");
}
6.2 边界检查 #
carbon
var arr: [i32; 5] = (1, 2, 3, 4, 5);
// 安全访问
match (arr.Get(10)) {
case Some(v) => Print("{0}", v);
case None => Print("越界");
}
6.3 悬垂引用防护 #
carbon
fn DanglingRef() -> i32& {
var x: i32 = 42;
return x; // 编译错误:返回局部变量的引用
}
// 正确做法
fn SafeRef(x: i32&) -> i32& {
return x;
}
七、RAII #
7.1 资源管理 #
carbon
class File {
private var handle_: i32;
fn New(path: String) -> File {
return File(handle_ = OpenFile(path));
}
fn Delete(me&) {
if (me.handle_ != -1) {
CloseFile(me.handle_);
me.handle_ = -1;
}
}
fn Read(me, buffer: [u8]&. i32 size) -> i32 {
return ReadFile(me.handle_, buffer, size);
}
}
fn Example() {
var file: File = File.New("data.txt");
// 使用文件
// 函数结束时自动关闭
}
7.2 作用域守卫 #
carbon
fn Example() {
var resource: Resource = AcquireResource();
defer {
ReleaseResource(resource);
}
// 使用资源
// 无论如何退出作用域,都会执行defer
}
八、内存布局 #
8.1 结构体布局 #
carbon
struct Point {
var x: f64; // 8字节
var y: f64; // 8字节
}
Print("Point大小: {0}", Point.Size); // 16字节
8.2 内存对齐 #
carbon
struct Example {
var a: u8; // 1字节
// 7字节填充
var b: f64; // 8字节
var c: u8; // 1字节
// 7字节填充
}
Print("Example大小: {0}", Example.Size); // 24字节
// 使用packed减少填充
packed struct PackedExample {
var a: u8; // 1字节
var b: f64; // 8字节
var c: u8; // 1字节
}
Print("PackedExample大小: {0}", PackedExample.Size); // 10字节
8.3 查看布局 #
carbon
Print("偏移量 a: {0}", Example.OffsetOf("a")); // 0
Print("偏移量 b: {0}", Example.OffsetOf("b")); // 8
Print("偏移量 c: {0}", Example.OffsetOf("c")); // 16
九、最佳实践 #
9.1 优先使用引用 #
carbon
// 好的做法:使用引用
fn Process(data: String&) {
// ...
}
// 避免:使用指针(除非需要空值)
fn Process(data: String*) {
if (data == nullptr) {
return;
}
// ...
}
9.2 使用智能指针 #
carbon
// 好的做法:使用智能指针
var ptr: UniquePtr(Resource) = MakeUnique(Resource());
// 避免:手动管理
var ptr: Resource* = new Resource();
// ... 容易忘记 delete
9.3 避免内存泄漏 #
carbon
// 好的做法:使用RAII
{
var file: File = File.New("data.txt");
// 自动关闭
}
// 避免:手动管理
{
var f: i32 = OpenFile("data.txt");
// 可能忘记关闭
}
十、总结 #
本章我们学习了:
- 指针:原始指针、空指针、指针运算
- 引用:引用基础、常量引用
- 所有权系统:所有权转移、借用规则
- 堆内存:动态分配、智能指针
- 内存安全:空指针检查、边界检查
- RAII:资源管理、作用域守卫
- 内存布局:结构体布局、内存对齐
接下来让我们学习Carbon的高级特性!
最后更新:2026-03-27