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 提升。