Delphi XE4不可变字符串

时间:2013-04-25 10:31:31

标签: delphi delphi-xe4

使用适用于iOS平台的Delphi XE4,引入了一种新的字符串类型:不可变的基于零的字符串。到目前为止,Delphi在写可变字符串上有副本。所以问题是,这对我未来的编程意味着什么?一种字符串类型比另一种字符串有什么优势吗?当切换到新的字符串类型时,我需要注意哪些陷阱(除了明显的0对1基数)?

1 个答案:

答案 0 :(得分:17)

根据Marco Cantù's whitepaper,XE4 iOS目标中的string数据类型实际上并不是不可变的,尽管他似乎与自己相矛盾。

他说:

  

在新的基于Delphi LLVM的编译器中,有一种字符串类型,表示Unicode字符串(UTF16),并映射到Delphi XE3中的当前字符串类型(Windows编译器上UnicodeString类型的别名)。但是,这种新的字符串类型使用不同的内存管理模型。字符串类型仍然是引用计数,但它是不可变的,这意味着一旦构造了字符串内容就无法修改它。

然后他继续说:

  

换句话说,字符串现在是基于Unicode的,很快就会变成不可变的,并且引用计数

还有:

  

然而,当事情开始改变时,就是修改现有内容   字符串,而不是用新值替换它(在这种情况下,你得到一个   全新的字符串)但是当你修改它的一个元素时,如图所示   这行代码(也在上一节中,我在哪里   介绍了这个主题):

Str1 [3] := 'x';
     

所有Delphi编译器都使用写时复制语义:如果你是字符串   修改有多个引用,首先复制(调整   根据需要参与各种字符串的引用计数)和   后来修改过。

     

新编译器的功能与经典编译器非常相似。它   实现写时复制机制,除非有一个   对字符串的引用,在这种情况下,字符串被修改   地点。例如,考虑以下代码,输出   实际字符串的内存位置。

然后他展示了一个带有变异字符串的iOS设备的图片。

official documentation我们有:

  

字符串是不可变的(常量),因此您无法将字符串索引为   一个数组并操纵字符串中的字符。如果你试图   修改一个字符串,Delphi移动编译器可能会发出消息   W1068将来可能不支持修改字符串   (德尔福)。您可以指定消息x1068是否作为a发出   警告或错误。在“提示和警告”页面中,设置警告   “将字符串就地修改......”改为“true”或“error”。

所以我将所有这些解释为iOS编译器的XE4版本仍然具有可变字符串。开发人员真的不希望你再改变你的字符串,并告诉你字符串在移动编译器上是不可变的。但它们看起来仍然是可变的。去图!


但是,您已经注意到,在将来的版本中,字符串可能会变为不可变。

您可以通过设置

立即为将来的版本做好准备
{$WARN IMMUTABLE_STRINGS WARN}

可以让您了解变更的影响。如果你想扣上并停止改变字符串,你可以这样做:

{$WARN IMMUTABLE_STRINGS ERROR}

一旦你这样做,你将需要转换访问单个字符串元素的代码。我怀疑你会对这样的代码有多少感到惊讶。我刚刚编译了600,000行代码,只看到了120个警告实例。其中大部分是第三方单位。我看到这个变化引起了不小的轰动,但老实说,我不相信很多代码会改变字符串。在绝大多数情况下,字符串是通过串联或通过调用Format等函数构建的。该代码不受此影响。

我认为没有任何重大缺陷。您可以使用{$WARN IMMUTABLE_STRINGS ...}让编译器指导您完成整个过程。任何改变字符串的代码都应转换为使用TStringBuilder

至于不变性的好处,我建议您Why .NET String is immutable?

如果您使用的是传统的Windows或OSX编译器,那么我认为没有令人信服的理由进行更改。 iOS编译器是全新的。对不可变字符串的更改已经浮动,但可能永远不会发生。它可能只发生在移动编译器上,而不会发生在传统的编译器上。现在,我会坐下来,等着看它是如何发挥作用的。