2.8 内存管理

December 6, 2025 · View on GitHub

CovScript 提供了灵活的内存管理机制,包括自动内存管理和手动内存控制。

2.8.1 new 关键字

new 关键字用于创建对象实例。

# 创建基本对象
var list = new list
var map = new hash_map
var set = new hash_set

# 创建自定义类实例
class Person
    var name = ""
    var age = 0
    
    function construct(n, a)
        this.name = n
        this.age = a
    end
end

var person = new Person{"Alice", 25}

# 创建结构体实例
struct Point
    var x = 0
    var y = 0
end

var point = new Point
point.x = 10
point.y = 20

对象生命周期

CovScript 使用栈进行自动内存管理。当栈解退时,会自动释放。

function createList()
    var list = new list
    list.push_back(1)
    list.push_back(2)
    list.push_back(3)
    return list
end

# list 在函数返回后继续存在
var myList = createList()

# 当 myList 超出作用域或被重新赋值时,对象会被自动释放
myList = null  # 显式释放引用

2.8.2 指针(pointer)

gcnew - 垃圾回收指针

gcnew 创建由垃圾回收器管理的指针。

# 创建 GC 管理的指针
var x = 42
var ptr = gcnew x

# 解引用指针
var value = *ptr
system.out.println(value)  # 42

# 修改指针指向的值
*ptr = 100
system.out.println(*ptr)  # 100

# 指针会被自动管理,无需手动释放

指针与对象

class Data
    var value = 0
    
    function construct(v)
        this.value = v
    end
    
    function display()
        system.out.println("Value: " + to_string(this.value))
    end
end

# 方式1:直接创建对象(非指针)
var obj = new Data{42}
obj.display()  # 使用点运算符

# 方式2:创建指针对象
var objPtr = gcnew Data{100}
objPtr->display()  # 使用箭头运算符

# 方式3:获取现有对象的指针
var obj2 = new Data{200}
var ptr = &obj2
ptr->display()  # 使用箭头运算符

2.8.3 指针操作

解引用操作符(*)

获取指针指向的值。

var num = 100
var ptr = gcnew num

# 读取值
var value = *ptr
system.out.println("Value: " + to_string(value))

# 修改值
*ptr = 200
system.out.println("New value: " + to_string(*ptr))

箭头操作符(->)

访问指针指向对象的成员。

class Rectangle
    var width = 0
    var height = 0
    
    function construct(w, h)
        this.width = w
        this.height = h
    end
    
    function getArea()
        return this.width * this.height
    end
end

var rect = new Rectangle{10, 5}

# 对于普通对象,使用点运算符访问成员
var area = rect.getArea()
system.out.println("Area: " + to_string(area))

# 修改成员
rect.width = 20
system.out.println("New area: " + to_string(rect.getArea()))

# 如果需要指针,使用 gcnew 或 &
var rectPtr = gcnew Rectangle{30, 40}
var ptrArea = rectPtr->getArea()
system.out.println("Pointer area: " + to_string(ptrArea))

取址操作符(&)

获取变量的引用。

var x = 10
var ref = &x

# 修改引用会影响原变量
ref = 20
system.out.println(x)  # 20

# 函数参数传递引用
function increment(ref)
    ref += 1
end

var count = 5
increment(&count)
system.out.println(count)  # 6

2.8.4 move 语义

move 语义用于转移对象的所有权,避免不必要的拷贝。

# 移动对象
var list1 = new list
list1.push_back(1)
list1.push_back(2)
list1.push_back(3)

# 移动 list1 的内容到 list2
var list2 = move(list1)

# list1 现在为空或无效
# list2 拥有原来的数据
system.out.println("List2 size: " + to_string(list2.size))  # 3

移动语义在函数中的应用

function createLargeList()
    var list = new list
    for i=0,i < 1000,++i
        list.push_back(i)
    end
    return move(list)  # 移动而不是拷贝
end

var data = createLargeList()
system.out.println("Size: " + to_string(data.size))

移动与交换

# 使用 move 实现高效的 swap
function swap(a, b)
    var temp = move(a)
    a = move(b)
    b = move(temp)
end

var x = {1, 2, 3}
var y = {4, 5, 6}

swap(&x, &y)

# 现在 x 包含 {4, 5, 6}
# y 包含 {1, 2, 3}

2.8.5 引用与值的区别

值传递

function modifyValue(x)
    x = 100
end

var num = 10
modifyValue(num)
system.out.println(num)  # 10(未改变)

引用传递

function modifyReference(ref)
    ref = 100
end

var num = 10
modifyReference(&num)
system.out.println(num)  # 100(已改变)

对象传递(默认为引用)

class Counter
    var count = 0
    
    function increment()
        this.count += 1
    end
end

function incrementCounter(counter)
    counter.increment()
end

var c = new Counter
c.count = 5
incrementCounter(c)
system.out.println(c.count)  # 6(已改变)

2.8.6 内存管理实践

避免内存泄漏

# 好的实践:及时释放不需要的引用
var data = new hash_map
# 使用 data...

# 完成后释放
data = null

# 循环引用可能导致内存问题
class Node
    var value = 0
    var next = null
    
    function construct(v)
        this.value = v
    end
end

# 注意清理循环引用
var node1 = new Node{1}
var node2 = new Node{2}
node1.next = node2
node2.next = node1  # 循环引用

# 清理
node1.next = null
node2.next = null

资源管理

# 使用 RAII 模式管理资源
class FileHandler
    var file = null
    
    function construct(filename)
        this.file = iostream.fstream(filename, iostream.openmode.in)
    end
    
    function read()
        if this.file != null
            return this.file.getline()
        end
        return null
    end
    
    function close()
        if this.file != null
            this.file.close()
            this.file = null
        end
    end
end

# 使用
var handler = new FileHandler{"data.txt"}
var line = handler.read()
handler.close()

2.8.7 完整示例:智能指针模拟

class SmartPointer
    var ptr = null
    var refCount = null
    
    function construct(obj)
        this.ptr = obj
        this.refCount = gcnew 1
    end
    
    function get()
        return this.ptr
    end
    
    function addRef()
        if this.refCount != null
            *this.refCount += 1
        end
    end
    
    function release()
        if this.refCount != null
            *this.refCount -= 1
            if *this.refCount == 0
                this.ptr = null
                this.refCount = null
                system.out.println("Object released")
            end
        end
    end
    
    function getRefCount()
        if this.refCount != null
            return *this.refCount
        end
        return 0
    end
end

# 使用智能指针
var obj = new hash_map
var sp1 = new SmartPointer{obj}

system.out.println("Ref count: " + to_string(sp1.getRefCount()))  # 1

var sp2 = sp1
sp2.addRef()
system.out.println("Ref count: " + to_string(sp1.getRefCount()))  # 2

sp2.release()
system.out.println("Ref count: " + to_string(sp1.getRefCount()))  # 1

sp1.release()
# 输出:Object released

2.8.8 内存性能优化

预分配容器

# 预分配列表容量(如果支持)
var list = new list
# list.reserve(1000)  # 预留空间

for i=0,i < 1000,++i
    list.push_back(i)
end

复用对象

# 对象池模式
class ObjectPool
    var available = new list
    var inUse = new list
    
    function construct()
        # 预创建一些对象
        for i=0,i < 10,++i
            this.available.push_back(new MyObject{})
        end
    end
    
    function acquire()
        if this.available.size > 0
            var obj = this.available.back
            this.available.pop_back()
            this.inUse.push_back(obj)
            return obj
        end
        
        # 创建新对象
        var obj = new MyObject{}
        this.inUse.push_back(obj)
        return obj
    end
    
    function release(obj)
        # 从 inUse 移除并放回 available
        # 简化实现
        this.available.push_back(obj)
    end
end

内存管理最佳实践

  1. 使用自动内存管理:优先依赖引用计数,避免手动管理
  2. 及时释放大对象:不再需要时置为 null
  3. 避免循环引用:注意对象之间的引用关系
  4. 使用 move 优化性能:大对象转移所有权时使用 move
  5. 注意作用域:合理使用局部变量减少内存占用
# 好的实践
function processData(filename)
    var data = loadLargeFile(filename)
    var result = transformData(data)
    data = null  # 及时释放
    return result
end

# 避免在循环中创建大对象
var cache = new hash_map
for i=0,i < 1000,++i
    if !cache.exist(i)
        cache.insert(i, createExpensiveObject(i))
    end
    processWithCache(i, cache)
end