值类型
Sric中变量默认是值类型的,值类型在传递和赋值的时候会自动拷贝。而指针类型在传递和赋值的时候只拷贝了指针本身,指针指向的对象没有被拷贝。
指针
- 指针分为所有权指针、非所有权指针、裸指针。
- 和C/C++不同的是,指针的*号放在类型的前方。
var p: Int //值类型
var p: own* Int //所有权指针
var p: * Int //非所有权指针
var p: & Int //引用
var p: raw* Int //裸指针
var p: uniq* Int //唯一所有权指针
Sric也有和C++类似的一系列智能指针,以库的形式提供。包括SharedPtr、WeakPtr等,见标准库相关章节的描述。
内存分配
指针可以通过值类型取地址获得,但更常用的是通过new关键字在堆上分配内存。
var i: own* Int = new Int
new后面的类型没有括号(因为Sric不支持有参构造函数)。new分配的对象为所有权指针。
所有权指针
- 所有权指针表示拥有所指对象,在作用域结束时自动释放对象。
- 传递或者赋值所有权指针时需要显式移动或者拷贝。
var p1: own* Int = ...
var p2 = move p1
var p3 = share(p1)
使用share函数,从一个所有权指针分裂出新的所有权指针,多个指针指向同一个内存地址。
唯一所有权指针
uniq*是零开销的。和own*类似,但没有share()方法。
var p1: uniq* Int = makeUniq$<Int>()
var p2 = move p1
非所有权指针
- 非所有权指针使用没有限制,不会像Rust那样有借用限制。
- 程序会在运行时检查所引用的对象是否有效。
own*和uniq*可以自动转换成非所有权指针和裸指针。
var p1: own* Int = ...
var p4: * Int = p1
var p5: raw* Int = p1
裸指针
裸指针是C/C++的指针,需要在安全模式中使用。
var p: raw* Int = ...
unsafe {
var i = *p
}
其他类型的指针可以自动转为裸指针类型。
取地址
值类型取地址运算后获得其指针。本地字段取地址后为非所有权指针(数组除外)。
var i: Int = 0
var p: *Int = &i
指针运算
只有裸指针才能进行指针运算。指针运算只能在unsafe块,或者unsafe函数中进行。
var p : raw* Int = ...
unsafe {
++p
p = p + 2
}
引用
引用的概念同C++,但在sric中引用只能用在函数参数和返回值中。
fun foo(a: & const Int) {
}
引用可以理解为自动解引用的指针。给引用赋值会修改原始的内容。
数组
数组特指静态大小数组。如果需要动态数组,请参考标准库中的DArray。
数组的括号写在类型前面
var a: [5]Int
数组初始化时可以省略数组大小,由编译器自动推断
var a = []Int { 1,3,4 }
数组大小也可用constexpr变量来指定。
constexpr var size: const Int = 15
var a: [size]Int
目前constexpr变量只能通过字面量初始化。
空指针安全
指针默认是不可以为null的,除非加问号声明。
var a: own*? B = null
var a: own* B = null //compile error
在必要时编译器会自动插入空指针检查,以保证空指针安全。
只有指针可以赋值为null,值类型和引用不能为空。
不可变性
和C++类似,const可以修饰指针本身,也可以修饰指针所指对象。
var p : raw* const Int
var p : const raw* Int
var p : const raw* const Int