所有权系统 #
一、所有权概念 #
1.1 什么是所有权 #
Mojo的所有权系统是一种内存管理机制,确保:
- 每个值都有一个所有者
- 值在同一时间只能有一个所有者
- 所有者离开作用域时,值被释放
1.2 所有权规则 #
- 每个值都有一个变量作为其所有者
- 同一时间只能有一个所有者
- 当所有者离开作用域,值将被丢弃
mojo
struct Resource:
var name: String
fn __init__(inout self, name: String):
self.name = name
print(f"{self.name} created")
fn __del__(owned self):
print(f"{self.name} destroyed")
def main():
let res = Resource("MyResource")
print("Using resource")
main()
二、所有权转移 #
2.1 转移语义 #
mojo
struct Buffer:
var data: Pointer[Int]
var size: Int
fn __init__(inout self, size: Int):
self.size = size
self.data = Pointer[Int].alloc(size)
fn __del__(owned self):
self.data.free()
fn take_buffer(owned b: Buffer):
print(f"Buffer size: {b.size}")
def main():
let buf = Buffer(10)
take_buffer(buf)
main()
2.2 转移后不可用 #
mojo
struct Item:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
fn consume(owned item: Item):
print(item.value)
def main():
let item = Item(42)
consume(item)
print(item.value)
main()
2.3 返回值所有权 #
mojo
struct Item:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
fn create_item() -> Item:
return Item(100)
def main():
let item = create_item()
print(item.value)
main()
三、借用 #
3.1 不可变借用 (ref) #
mojo
struct Data:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
fn read_data(ref d: Data):
print(d.value)
def main():
let data = Data(42)
read_data(data)
print(data.value)
main()
3.2 可变借用 (inout) #
mojo
struct Counter:
var value: Int
fn __init__(inout self, value: Int = 0):
self.value = value
fn increment(inout c: Counter):
c.value += 1
def main():
var counter = Counter()
increment(counter)
print(counter.value)
main()
3.3 借用规则 #
- 可以有多个不可变借用
- 只能有一个可变借用
- 不可变借用和可变借用不能同时存在
mojo
struct Data:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
fn read1(ref d: Data):
print(d.value)
fn read2(ref d: Data):
print(d.value)
fn modify(inout d: Data):
d.value += 1
def main():
var data = Data(10)
read1(data)
read2(data)
modify(data)
print(data.value)
main()
四、引用类型 #
4.1 ref参数 #
mojo
struct Point:
var x: Int
var y: Int
fn __init__(inout self, x: Int, y: Int):
self.x = x
self.y = y
fn distance(ref p1: Point, ref p2: Point) -> Float64:
let dx = p2.x - p1.x
let dy = p2.y - p1.y
return (dx * dx + dy * dy) ** 0.5
def main():
let p1 = Point(0, 0)
let p2 = Point(3, 4)
print(distance(p1, p2))
main()
4.2 inout参数 #
mojo
struct Point:
var x: Int
var y: Int
fn __init__(inout self, x: Int, y: Int):
self.x = x
self.y = y
fn translate(inout p: Point, dx: Int, dy: Int):
p.x += dx
p.y += dy
def main():
var point = Point(10, 20)
translate(point, 5, 5)
print(f"({point.x}, {point.y})")
main()
4.3 owned参数 #
mojo
struct Resource:
var name: String
fn __init__(inout self, name: String):
self.name = name
print(f"{self.name} acquired")
fn __del__(owned self):
print(f"{self.name} released")
fn use_resource(owned r: Resource):
print(f"Using {r.name}")
def main():
let res = Resource("Database")
use_resource(res)
print("Done")
main()
五、生命周期 #
5.1 生命周期注解 #
mojo
struct StringRef:
ref var data: String
fn __init__(inout self, ref s: String):
self.data = s
fn get(self) -> ref String:
return self.data
def main():
let text = "Hello"
var sref = StringRef(text)
print(sref.get())
main()
5.2 生命周期约束 #
mojo
struct Container:
ref var item: Item
fn __init__(inout self, ref i: Item):
self.item = i
struct Item:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
def main():
let item = Item(42)
let container = Container(item)
print(container.item.value)
main()
六、复制与移动 #
6.1 复制语义 #
mojo
struct SimpleValue:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
fn __copyinit__(inout self, other: SimpleValue):
self.value = other.value
def main():
let v1 = SimpleValue(10)
let v2 = v1
print(v1.value)
print(v2.value)
main()
6.2 移动语义 #
mojo
struct UniqueResource:
var id: Int
fn __init__(inout self, id: Int):
self.id = id
fn __moveinit__(inout self, owned other: UniqueResource):
self.id = other.id
other.id = 0
def main():
var r1 = UniqueResource(100)
var r2 = r1
print(r2.id)
main()
6.3 禁止复制 #
mojo
struct NonCopyable:
var data: Pointer[Int]
fn __init__(inout self, size: Int):
self.data = Pointer[Int].alloc(size)
fn __del__(owned self):
self.data.free()
def main():
let nc = NonCopyable(10)
main()
七、所有权最佳实践 #
7.1 优先使用借用 #
mojo
struct Data:
var values: List[Int]
fn __init__(inout self):
self.values = [1, 2, 3, 4, 5]
fn process(ref d: Data):
for v in d.values:
print(v)
def main():
let data = Data()
process(data)
process(data)
main()
7.2 明确所有权转移 #
mojo
struct Buffer:
var data: Pointer[Int]
var size: Int
fn __init__(inout self, size: Int):
self.size = size
self.data = Pointer[Int].alloc(size)
fn __del__(owned self):
if self.data != nullptr:
self.data.free()
fn transfer_buffer(owned b: Buffer) -> Buffer:
return b
def main():
let buf1 = Buffer(10)
let buf2 = transfer_buffer(buf1)
main()
7.3 使用RAII #
mojo
struct FileHandle:
var path: String
var handle: Int
fn __init__(inout self, path: String):
self.path = path
self.handle = open_file(path)
print(f"Opened {self.path}")
fn __del__(owned self):
close_file(self.handle)
print(f"Closed {self.path}")
fn open_file(path: String) -> Int:
return 1
fn close_file(handle: Int):
pass
def main():
let file = FileHandle("data.txt")
print("Processing file")
main()
八、常见问题 #
8.1 悬垂引用 #
mojo
fn create_ref() -> ref Int:
let local = 10
return local
def main():
let r = create_ref()
main()
8.2 双重释放 #
mojo
struct Resource:
var ptr: Pointer[Int]
fn __init__(inout self):
self.ptr = Pointer[Int].alloc(10)
fn __del__(owned self):
self.ptr.free()
def main():
let r1 = Resource()
let r2 = r1
main()
8.3 数据竞争 #
mojo
struct SharedData:
var value: Int
fn __init__(inout self, value: Int):
self.value = value
fn read_write(ref d: SharedData):
print(d.value)
d.value += 1
def main():
var data = SharedData(10)
read_write(data)
main()
九、总结 #
本章学习了:
- 所有权概念与规则
- 所有权转移
- 借用机制
- 引用类型
- 生命周期
- 复制与移动语义
- 最佳实践
下一章,我们将学习指针与引用。
最后更新:2026-03-27