Skip to content

变量初始化器


变量初始化器支持初始化预建类型变量、UDT 对象和数组。

前言:

预建类型变量、用户自定义类型(UDT)对象和数组在创建时默认初始化为零(或 'Boolean' 类型的 'False')或空字符串。

为避免默认变量初始化的开销,可以使用 'Any' 初始化器与 'Dim' 一起告诉编译器只为变量保留内存空间而不初始化它,这样变量将包含垃圾值。在这种情况下,程序员不应对初始值做任何假设。

预建类型变量、UDT 对象和数组可以使用 'Dim ...' 在声明时赋值,使用下面所示的语法。

预建类型变量、UDT 对象和数组的初始化方式与正常赋值相同,使用 '=' 符号。也可以使用 '=>' 符号,例如在声明固定长度字符串时可以避免声明看起来像表达式。

目录

1. 预建类型变量声明的初始化器语法和有效性

2. UDT 对象声明的初始化器语法和有效性

3. 数组声明的初始化器语法和有效性

4. 嵌套初始化器语法


1. 预建类型变量声明的初始化器语法和有效性

主要的预建类型包括:

  • 整数类型

  • 浮点类型

  • 布尔类型

  • 字符串类型

初始化器语法

以下描述 4 种基本语法。

带初始化器的静态分配:

(1) Dim variable_symbol [As PreBuiltType] = expression

或:

(2) Dim Byref ref_variable_symbol [As PreBuiltType] = variable

带初始化器的动态分配:

(3) Dim ptr_variable_symbol As PreBuiltType Ptr = New PreBuiltType( expression )

或:

(4) Dim Byref ref_variable_symbol As PreBuiltType = *New PreBuiltType( expression )

初始化器有效性

  • expression

必须产生 'PreBuiltType' 类型或兼容类型的求值值。

  • variable

指定了 'As PreBuiltType' 时,为 'PreBuiltType' 变量或兼容变量。

全局符号的声明语法

如果在带初始化器的预建类型变量声明中使用全局符号('Dim Shared''Static [Shared]''Static Var [Shared]' 代替 'Dim'),初始化器参数必须至少能够在程序启动时求值,以便可以放置在 .data 节中:

  • 可变长度字符串的初始化器语法不再有效,因为 'variable_symbol' 必须指向堆中的动态内存块。

  • 对于其他预建类型变量,如果提供的参数可以在编译时求值,初始化器语法仍然有效。

示例

start GeSHi

vb
Dim d As Double = 1234.56789

Print d

Sleep

end GeSHi

注意:

仅在 -lang fb 中,可以使用 'Var' 代替 'Dim'(删除显式类型声明),'Wstring' 类型的初始化器值除外。

返回顶部


2. UDT 对象声明的初始化器语法和有效性

UDT(用户自定义类型)是用户定义的类型结构,是对已有预建类型的补充。

以下所有内容假设下面的任何语句(1 到 7)都有权访问 UDT 中显式定义的任何构造函数(如果存在)。

初始化器语法

以下描述 7 种基本语法。

带初始化器的静态分配:

(1) Dim udt_symbol As UdtName = ( argument_list )

或:

(2) Dim udt_symbol As UdtName = udt_instance

或:

(3) Dim Byref ref_udt_symbol As UdtName = udt_instance

或:

(4) Dim udt_symbol As UdtName = UdtName( argument_list )

或:

(5) Dim udt_symbol As UdtName = Type[<UdtName>]( argument_list )

带初始化器的动态分配:

(6) Dim ptr_udt_symbol As UdtName Ptr = New UdtName( argument_list )

或:

(7) Dim Byref ref_udt_symbol As UdtName = *New UdtName( argument_list )

参数

  • argument_list

任何参数类型的列表(以逗号分隔的项)。

如果只有一个参数,'= Type[<UdtName>]( argument )' 初始化器(如果有效)可以缩短为 '= ( argument )' 甚至 '= argument'(转换构造函数的情况)。

  • udt_instance

'UdtName' 或兼容类型(派生类型)的实例。

初始化器有效性

  • 初始化器语法第 (1) 行

仅当不存在构造函数(既非隐式也非显式)时有效。

  • 初始化器语法第 (2 或 3) 行

始终有效。

拷贝构造(2)和引用声明(3)的情况。

  • 初始化器语法第 (4) 行

仅当存在与 'argument_list' 匹配的隐式或显式构造函数时有效。

  • 初始化器语法第 (5) 行

仅当不存在构造函数(既非隐式也非显式),或者存在至少一个与 'argument_list' 匹配的构造函数(隐式或显式)时有效。

  • 初始化器语法第 (6 或 7) 行

其有效性遵循与上面 初始化器语法第 (5) 行 相同的规则。

但是,决定隐式构造函数是否存在的规则最为复杂,这取决于类型结构:

  • 除默认构造函数和默认拷贝构造函数外,任何其他类型的构造函数仅在显式定义时才存在。

  • 对于隐式默认构造函数和隐式拷贝构造函数,它取决于类型结构,例如它们两者都存在于(主要情况):

  • 具有或继承了具有隐式/显式默认构造函数的成员字段的类型(包括字符串成员),

  • 或具有具有隐式/显式默认构造函数的基类的类型(包括从 Object) 派生的类型),

  • ....,

  • 否则例如,只有具有初始化器本身的变量成员只会导致隐式默认构造函数,但没有隐式拷贝构造函数。

描述

当 UDT 有隐式构造函数(由于字符串成员,或具有初始化器本身的变量成员,或具有构造函数的数据成员,或从 Object 派生的 UDT,或自 fbc 版本 1.20.0 起包含 STRING*N 字段加另一个数据类型字段)或显式构造函数时,简单的初始化器如 '= ( argument_list )'(列表中的第一个初始化器语法 (1))不再有效。

在这种情况下,可以通过使用与列表中最后四种语法(4 到 7)的初始化表达式匹配的构造函数来应用高级初始化。

列表中较简单的初始化器语法(第一个 (1))始终可以被列表中最后四种初始化器语法(4 到 7)之一替换,但反之不行。

列表中的第二种初始化器语法 (2) 是拷贝构造的特殊情况。这种初始化器语法始终有效,无论是通过默认拷贝构造还是通过拷贝构造函数(隐式或显式)。

列表中的第三种初始化器语法 (3) 是引用声明的特殊情况,必须始终有初始化器。如果 'udt_instance' 是引用(或解引用的指针),这种初始化器语法始终有效。

全局符号的声明语法

如果在带初始化器的 UDT 对象声明中使用全局符号('Dim Shared''Static [Shared]''Static Var [Shared]' 代替 'Dim'),初始化器参数必须至少能够在程序启动时求值,以便可以放置在 .data 节中:

  • 列表中的初始化器语法 (6) 和 (7) 不再有效,因为符号必须指向堆中的动态内存块。

  • 如果提供的参数可以在编译时求值,其他初始化器语法仍然有效。如果初始化器必须调用现有构造函数(隐式或显式),则程序启动时调用的构造函数代码会将"初始"值写入 .data 节。

注释示例

start GeSHi

vb
Type UDT1
    Dim As Integer I
    Dim As Integer J
End Type

Dim As UDT1 u11 = (1, 2)                  '' default-construction + initialization
'Dim As UDT1 u12 = UDT1(1, 2)             '' not valid: no Constructor(As Integer, As Integer)
Dim As UDT1 u13 = Type<UDT1>(1, 2)        '' default-construction + initialization
Dim As UDT1 Ptr pu14 = New UDT1(1, 2)     '' default-construction + initialization
    Delete pu14
Dim ByRef As UDT1 ru15 = *New UDT1(1, 2)  '' default-construction + initialization
    Delete @ru15
   
Dim As UDT1 u16 = u13                     '' default copy-construction
'Dim As UDT1 u17 = UDT1(u13)              '' not valid: no implicit Constructor(As UDT1)
Dim As UDT1 u18 = Type<UDT1>(u13)         '' default-construction + initialization
Dim As UDT1 Ptr pu19 = New UDT1(u13)      '' default-construction + initialization
    Delete pu19
Dim ByRef As UDT1 ru110 = *New UDT1(u13)  '' default-construction + initialization
    Delete @ru110
Print

Type UDT2
    Dim As Integer I = Any
    Dim As Integer J
    Declare Constructor ()
    Declare Constructor (ByVal _I As Integer, ByVal _J As Integer)
End Type
Constructor UDT2 ()
    Print "UDT2.Constructor()"
End Constructor
Constructor UDT2 (ByVal _I As Integer, ByVal _J As Integer)
    Print "UDT2.Constructor(Byval As Integer, Byval As Integer)"
    This.I = _I
    This.J = _J
End Constructor

'Dim As UDT2 u21 = (1, 2)                  '' not valid: exist constructor (due at least to '= Any' initialiser)
Dim As UDT2 u22 = UDT2(1, 2)               '' call Constructor(As Integer, As Integer)
Dim As UDT2 u23 = Type<UDT2>(1, 2)         '' call Constructor(As Integer, As Integer)
Dim As UDT2 Ptr pu24 = New UDT2(1, 2)      '' call Constructor(As Integer, As Integer)
    Delete pu24
Dim ByRef As UDT2 ru25 = *New UDT2(1, 2)   '' call Constructor(As Integer, As Integer)
    Delete @ru25
   
Dim As UDT2 u26 = u23                      '' default copy-construction
'Dim As UDT2 u27 = UDT2(u23)               '' not valid: no implicit Constructor(As UDT2)
'Dim As UDT2 u28 = Type<UDT2>(u23)         '' not valid: no implicit Constructor(As UDT2)
'Dim As UDT2 Ptr pu29 = New UDT2(u23)      '' not valid: no implicit Constructor(As UDT2)
'Dim Byref As UDT2 ru210 = *New UDT2(u23)  '' not valid: no implicit Constructor(As UDT2)
Print

Type UDT3
    Dim As Integer I
    Dim As String S
    Declare Constructor ()
    Declare Constructor (ByVal _I As Integer, ByRef _S As Const String)
End Type
Constructor UDT3 ()
    Print "UDT3.Constructor()"
End Constructor
Constructor UDT3 (ByVal _I As Integer, ByRef _S As Const String)
    Print "UDT3.Constructor(Byval As Integer, Byref As Const String)"
    This.I = _I
    This.S = _S
End Constructor

'Dim As UDT3 u31 = (1, "2")                 '' not valid: exist constructor (due at least to string member)
Dim As UDT3 u32 = UDT3(1, "2")              '' call Constructor(As Integer, As String)
Dim As UDT3 u33 = Type<UDT3>(1, "2")        '' call Constructor(As Integer, As String)
Dim As UDT3 Ptr pu34 = New UDT3(1, "2")     '' call Constructor(As Integer, As String)
    Delete pu34
Dim ByRef As UDT3 ru35 = *New UDT3(1, "2")  '' call Constructor(As Integer, As String)
    Delete @ru35
   
Dim As UDT3 u36 = u33                       '' default copy-construction
Dim As UDT3 u37 = UDT3(u33)                 '' call implicit Constructor(As UDT3)
Dim As UDT3 u38 = Type<UDT3>(u33)           '' call implicit Constructor(As UDT3)
Dim As UDT3 Ptr pu39 = New UDT3(u33)        '' call implicit Constructor(As UDT3)
    Delete pu39
Dim ByRef As UDT3 ru310 = *New UDT3(u33)    '' call implicit Constructor(As UDT3)
    Delete @ru310
Print

Type UDT4 Extends Object
    Dim As Integer I
    Dim As Integer J
    Declare Constructor ()
    Declare Constructor (ByVal _I As Integer, ByVal _J As Integer)
End Type
Constructor UDT4 ()
    Print "UDT4.Constructor()"
End Constructor
Constructor UDT4 (ByVal _I As Integer, ByVal _J As Integer)
    Print "UDT4.Constructor(Byval As Integer, Byval As Integer)"
    This.I = _I
    This.J = _J
End Constructor

'Dim As UDT4 u41 = (1, 2)                 '' not valid: exist constructor (due at least to Object as base)
Dim As UDT4 u42 = UDT4(1, 2)              '' call Constructor(As Integer, As Integer)
Dim As UDT4 u43 = Type<UDT4>(1, 2)        '' call Constructor(As Integer, As Integer)
Dim As UDT4 Ptr pu44 = New UDT4(1, 2)     '' call Constructor(As Integer, As Integer)
    Delete pu44
Dim ByRef As UDT4 ru45 = *New UDT4(1, 2)  '' call Constructor(As Integer, As Integer)
    Delete @ru45
   
Dim As UDT4 u46 = u43                     '' default copy-construction
Dim As UDT4 u47 = UDT4(u43)               '' call implicit Constructor(As UDT4)
Dim As UDT4 u48 = Type<UDT4>(u43)         '' call implicit Constructor(As UDT4)
Dim As UDT4 Ptr pu49 = New UDT4(u43)      '' call implicit Constructor(As UDT4)
    Delete pu49
Dim ByRef As UDT4 ru410 = *New UDT4(u43)  '' call implicit Constructor(As UDT4)
    Delete @ru410
Print

' Note for static UDT declaration + initializer:
'    When the initializer expression calling the constructor has only one parameter 'x', example:
'    'Dim As UDT u = UDT(x)', in this case, 'UDT(x)' can be shortened into '(x)' or even 'x', like:
'    'Dim As UDT u = (x)' or even 'Dim As UDT u = x', but all these statements call the constructor.
'    (a constructor with one parameter is called a conversion-constructor)

' The six below declarations + initialisers all call only the conversion-constructor

Type UDT5
    Dim As Integer I
    Declare Constructor ()
    Declare Constructor (ByVal _I As Integer)
End Type
Constructor UDT5 ()
    Print "UDT5.Constructor()"
End Constructor
Constructor UDT5 (ByVal _I As Integer)
    Print "UDT5.Constructor(Byval As Integer)"
    This.I = _I
End Constructor

Dim As UDT5 u51 = UDT5(1)                  '' call Constructor(As Integer)
Dim As UDT5 u52 = Type<UDT5>(1)            '' call Constructor(As Integer)
Dim As UDT5 u53 = (1)                      '' call Constructor(As Integer)
Dim As UDT5 u54 = 1                        '' call Constructor(As Integer)
Dim As UDT5 Ptr pu55 = New UDT5(1)         '' call Constructor(As Integer)
    Delete pu55
Dim ByRef As UDT5 ru56 = *New UDT5(1)      '' call Constructor(As Integer)
    Delete @ru56
   
Dim As UDT5 u57 = u54                      '' default copy-construction
'Dim As UDT5 u58 = UDT5(u54)               '' not valid: no implicit Constructor(As UDT5)
'Dim As UDT5 u59 = Type<UDT5>(u54)         '' not valid: no implicit Constructor(As UDT5)
'Dim As UDT5 Ptr pu510 = New UDT5(u54)     '' not valid: no implicit Constructor(As UDT5)
'Dim Byref As UDT5 ru511 = *New UDT5(u54)  '' not valid: no implicit Constructor(As UDT5)
Print

Sleep

end GeSHi

注意:

仅在 -lang fb 中,可以使用 'Var' 代替 'Dim'(删除显式类型声明),但初始化器值的类型不能有歧义。

在上面的示例中,只有 'Var u11 = (1, 2)' 不起作用,但 'Var u13 = Type<UDT1>(1, 2)' 可以工作。

返回顶部


3. 数组声明的初始化器语法和有效性

数组可以是任何 DataType

初始化器语法

以下描述 1 种基本语法。

(目前不支持引用数组)

Dim array_symbol ([lbound To] ubound) [AS DataType] = { expression [, ...] }

参数

  • 'lbound''ubound'

常量数值。

  • 'expression(s)'

以逗号分隔的项给出的列表,然后用花括号括起来。

初始化列表从 'lbound''ubound' 排序。

必须产生 'DataType' 类型或兼容类型的求值值。

初始化器有效性

'lbound''ubound' 必须是常量数值,因为可变长度(动态)数组声明不支持任何初始化器。

只有固定长度(静态)数组声明支持初始化器。

全局符号的声明语法

如果在带初始化器的数组变量声明中使用全局符号('Dim Shared''Static [Shared]' 代替 'Dim'),初始化器参数必须至少能够在程序启动时求值,以便可以放置在 .data 节中:

  • 可变长度字符串的固定长度(静态)数组的初始化器语法不再有效,因为符号必须指向堆中的动态内存块。

  • 对于其他预建类型变量的固定长度(静态)数组,如果提供的表达式可以在编译时求值,初始化器语法仍然有效。

示例

start GeSHi

vb
Dim array(0 To 4) As String = {"array(0)", "array(1)", "array(2)", "array(3)", "array(4)"}

For I As Integer = 0 To 4
    Print array(I),
Next I
Print

Sleep

end GeSHi

注意:

即使在 -lang fb 中,也不能使用 'Var' 代替 'Dim',因为 'Var' 不支持数组声明。

返回顶部


4. 嵌套初始化器语法

这些初始化变量的方法可以相互嵌套以进行复杂赋值。

例如,初始化多维数组:

start GeSHi

vb
Dim array(1 To 3, 1 To 5) As Integer = _
    { _
        {11, 12, 13, 14, 15}, _
        {21, 22, 23, 24, 25}, _
        {31, 32, 33, 34, 35} _
    }

For I As Integer = 1 To 3
    For J As Integer = 1 To 5
        Print array(I, J),
    Next J
    Print
Next I

Sleep

end GeSHi

在这个声明中,最左维度的值以 5 元素数组的形式给出。

嵌套允许初始化任意维度的数组。

UDT 和数组也可以相互嵌套。

例如,以下代码声明并初始化一个 UDT 数组:

start GeSHi

vb
Type mytype
    var1 As Double
    var2 As Integer
    var3 As ZString Ptr
End Type

Dim MyVar(0 To 1) As mytype = _
    { _
        (1.1, 1, @"Hello"), _
        (2.2, 2, @"GoodBye") _
    }

For I As Integer = 0 To 1
    Print MyVar(I).var1, MyVar(I).var2, *MyVar(I).var3
Next I

Sleep

end GeSHi

注意:

即使在 -lang fb 中,也不能使用 'Var' 代替 'Dim',因为 'Var' 不支持数组声明。

返回顶部


方言差异

  • -lang qb 方言中,变量不能初始化。
  • -lang fblite 方言中,'Dim ... = ...' 中可以省略显式类型声明,但仅适用于 Integer 类型(初始化器值必须与 Integer 类型匹配)。

与 QB 的差异

  • 变量初始化器是 FreeBASIC 新增的。
  • 替代语法 'Dim [Byref] As DataType symbolname = ...' 是 FreeBASIC 新增的。

另请参阅

返回 目录

基于 FreeBASIC 官方文档翻译 如有侵权请联系我们删除
FreeBASIC 是开源项目,与微软公司无隶属关系