# VarSetStrCapacity

增加变量的容量或释放其内存. 一般情况下不需要, 但可以与 DllCall 或 SendMessage 一起使用, 或者优化重复连接.

    GrantedCapacity := VarSetStrCapacity(&TargetVar , RequestedCapacity)

## 参数

&TargetVar

  类型: VarRef

  变量的引用. 例如: `VarSetStrCapacity(&MyVar, 1000)`. 这也可以是动态变量, 例如 `Array%i%` 或是函数的 ByRef 参数.

RequestedCapacity

  类型: 整数

  如果省略, 则函数将返回变量当前的容量且不会改变其的内容. 否则, 变量中的所有内容将会丢弃(变量被置空).

  指定 RequestedCapacity 为调整后变量所能容纳的字节数. RequestedCapacity 不包括内部零终止符. 例如, 指定 1 将允许变量在其内部结束符之外最多容纳一个字符. 注意: 如果脚本稍后给它分配一个更大的值, 变量将自动展开.

  因此可以经常简单地调用此函数来确保变量占用最小的空间, 出于性能的考虑, 它只在 RequestedCapacity 为 0 的时候才会缩小变量. 换句话说, 如果变量的容量已经大于 RequestedCapacity, 它就不会被缩小(但为了保持一致性, 变量会被置空).

  因此, 要显式地缩小变量, 首先请使用 `VarSetStrCapacity(&Var, 0)` 释放它占用的内存, 然后使用 `VarSetStrCapacity(&Var, NewCapacity)` -- 或者简单地让它自动按需从零扩展.

  出于性能考虑, 要释放一个原来容量小于 64 字符的变量可能会没有效果, 因为它的内存是永久类型的. 在这种情况下, 会返回当前容量, 而不是 0.

  出于性能考虑, 容量小于 4096 字节的变量的内存不能通过赋值空字符串的方法来释放(例如 `Var := ""`). 然而, `VarSetStrCapacity(&Var, 0)` 可释放它.

  为 RequestedCapacity 指定 -1, 将变量内部存储的字符串长度更新为其当前内容的长度. 这在字符串被间接改变的情况下很有用, 比如通过 DllCall 或 SendMessage 传递其地址. 在这种模式下, VarSetStrCapacity 返回的是长度而不是容量.

## 返回值

类型: 整数

该函数返回 TargetVar 现在可以容纳的字符数, 该字符数将大于或等于 RequestedCapacity.

## 失败

在以下任何一种情况下都会抛出异常:

- VarName 不是一个有效的变量引用. 不可能通过引用传递一个对象属性或内置变量, 因此不能将其传递给该函数.
- 请求的容量太大, 无法容纳在脚本可用的任何一个连续的内存块中. 在极少数情况下, 这可能是由于系统内存耗尽所致.
- RequestedCapacity 小于 -1 或大于当前平台理论上可以支持的容量.

## 备注

Buffer 对象在处理二进制数据, 结构体, DllCall 和类似的东西时, 提供了卓越的清晰度和灵活性. 例如, Buffer 对象可以分配给一个属性或数组元素, 或者传递给一个函数或从一个函数返回, 而不需要复制其内容.

在通过渐进式连接的方式构建一个字符串时, 可以使用这个函数来提高性能. 这是因为当你对字符串的最终长度有一定了解时, 可以避免多次自动调整大小. 在这种情况下, RequestedCapacity 不需要太准确: 如果容量太小, 性能仍然会得到提高, 当容量用完后, 变量将开始自动扩展. 如果容量过大, 则会浪费部分内存, 但只是暂时的, 因为所有的内存都可以在操作后通过 `VarSetStrCapacity(&Var, 0)` 或 `Var := ""` 来释放.

## 相关

Buffer 对象, DllCall, NumPut, NumGet

## 示例

通过确保 MyVar 有足够的工作空间来优化.

    VarSetStrCapacity(&MyVar, 5120000)  ; ~10 MB
    Loop
    {
        ; ...
        MyVar .= StringToConcatenate
        ; ...
    }

使用一个变量通过 DllCall 从外部函数接收一个字符串. (注意, 使用 Buffer 对象可能是首选; 尤其是在处理非 Unicode 字符串时.)

    max_chars := 10

    Loop 2
    {
        ; 分配用于 DllCall 的空间.
        VarSetStrCapacity(&buf, max_chars)

        if (A_Index = 1)
            ; 通过 DllCall 间接修改变量.
            DllCall("wsprintf", "Ptr", StrPtr(buf), "Str", "0x%08x", "UInt", 4919, "CDecl")
        else
            ; 使用 "str" 来自动更新长度:
            DllCall("wsprintf", "Str", buf, "Str", "0x%08x", "UInt", 4919, "CDecl")

        ; 连接字符串以演示为什么需要更新长度:
        wrong_str := buf . "<end>"
        wrong_len := StrLen(buf)

        ; 更新变量的长度.
        VarSetStrCapacity(&buf, -1)

        right_str := buf . "<end>"
        right_len := StrLen(buf)

        MsgBox
        (
        "Before updating
          String: " wrong_str "
          Length: " wrong_len "

        After updating
          String: " right_str "
          Length: " right_len
        )
    }

dftg