2.7. 克隆
克隆旨在创建数据的深层副本。 克隆是通过克隆运算符 ``:=``调用的:
a := b
也可以通过变量声明中的 clone 初始化器调用:
var x := y
这反过来又扩展为 clone_to_move
:
var x <- clone_to_move(y)
(参阅 clone_to_move).
2.7.1. 克隆规则和实现详细信息
克隆遵循几条规则。
某些类型(如 block、lambda 和迭代器)根本无法克隆。
但是,如果存在自定义克隆函数,则无论类型的可克隆性如何,都会立即调用该函数:
struct Foo {
a : int
}
def clone ( var x : Foo; y : Foo ) {
x.a = y.a
print("cloned\n")
}
var l = Foo(a=1)
var cl : Foo
cl := l // 调用 clone(cl,l)
通常允许在常规类型和临时类型之间进行克隆 (参阅 Temporary types).
POD 类型被复制而不是克隆:
var a,b : int
var c,d : int[10]
a := b
c := d
这扩展到:
a = b
c = d
处理类型通过 canClone
, simulateClone``和适当的``das_clone
C++基础设施提供自己的克隆功能 (参阅 Handles).
对于静态数组,调用 clone_dim
泛型,对于动态数组,调用 ‘clone
泛型。
这些元素反过来会克隆每个数组元素:
struct Foo {
a : array<int>
b : int
}
var a, b : array<Foo>
b := a
var c, d : Foo[10]
c := d
这扩展到:
def builtin`clone ( var a:array<Foo aka TT> explicit; b:array<Foo> const ) {
resize(a,length(b))
for ( aV,bV in a,b ) {
aV := bV
}
}
def builtin`clone_dim ( var a:Foo[10] explicit; b:Foo const[10] implicit explicit ) {
for ( aV,bV in a,b ) {
aV := bV
}
}
对于表,调用 clone
泛型,进而克隆其值:
var a, b : table<string;Foo>
b := a
这扩展到:
def builtin`clone ( var a:table<string aka KT;Foo aka VT> explicit; b:table<string;Foo> const ) {
clear(a)
for ( k,v in keys(b),values(b) ) {
a[k] := v
}
}
对于结构,会生成默认的 clone
函数,其中每个元素都被克隆:
struct Foo {
a : array<int>
b : int
}
这扩展到:
def clone ( var a:Foo explicit; b:Foo const ) {
a.a := b.a
a.b = b.b // 注意 复制而不是克隆
}
对于 Tuple,每个单独的元素都被克隆:
var a, b : tuple<int;array<int>;string>
b := a
这扩展到:
def clone ( var dest:tuple<int;array<int>;string> -const; src:tuple<int;array<int>;string> const -const ) {
dest._0 = src._0
dest._1 := src._1
dest._2 = src._2
}
对于变量,仅克隆当前活动的元素:
var a, b : variant<i:int;a:array<int>;s:string>
b := a
这扩展到:
def clone ( var dest:variant<i:int;a:array<int>;s:string> -const; src:variant<i:int;a:array<int>;s:string> const -const ) {
if ( src is i ) {
set_variant_index(dest,0)
dest.i = src.i
} elif ( src is a ) {
set_variant_index(dest,1)
dest.a := src.a
} elif ( src is s ) {
set_variant_index(dest,2)
dest.s = src.s
}
}
2.7.2. clone_to_move 实现
clone_to_move
作为内置模块的一部分通过常规泛型实现:
def clone_to_move(clone_src:auto(TT)) : TT -const {
var clone_dest : TT
clone_dest := clone_src
return <- clone_dest
}
请注意,对于不可克隆的类型,Daslang 不会将 :=
初始化为 clone_to_move
提升。