Delphi XE4不可变字符串

iam*_*osy 16 delphi delphi-xe4

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

Dav*_*nan 17

根据MarcoCantù 的白皮书,stringXE4 iOS目标中的数据类型实际上并不是一成不变的,尽管他似乎与自己相矛盾.

他说:

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

但他继续说:

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

并且:

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

Str1 [3] := 'x';
Run Code Online (Sandbox Code Playgroud)

所有Delphi编译器都使用写时复制语义:如果您修改的字符串有多个引用,则首先复制它(根据需要调整所涉及的各种字符串的引用计数),然后进行修改.

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

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

在我们的官方文档中:

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

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


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

您现在可以通过设置为将来的版本做好准备

{$WARN IMMUTABLE_STRINGS WARN}
Run Code Online (Sandbox Code Playgroud)

这将让您了解变化的影响.如果你想扣上并停止变异字符串,你可以这样做:

{$WARN IMMUTABLE_STRINGS ERROR}
Run Code Online (Sandbox Code Playgroud)

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

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

至于不变性的好处,我建议你为什么.NET String是不可变的?

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

  • Tim Anderson也对新的不可变移动字符串的不可变性感到困惑:http://www.itwriting.com/blog/7347-changes-in-the-delphi-language-for-arm-and-mobile-support html的 (3认同)
  • 哇,我有点害怕得出结论,但这听起来像Delphi开发人员的另一个坏主意.让我们打破兼容性,使字符串不那么有用,很棒的计划. (3认同)
  • @himself不可变性有益处.无论如何,这是一个影响非常小的变化.忽略其他人将要处理的第三方库,我可以在大约一个小时内修复我的代码库.我宁愿删掉一些语言,即使这意味着我们有些痛苦. (3认同)
  • @David Heffernan:任何使用字符串作为快速写入时复制存储的东西 - 见过很多.任何预先分配字符串的函数都会填充数据.(事实上​​,Delphi字符串一直在预先分配一些空间,但现在它们是不可变的我想知道s:= s + NextChar是否会非常慢) (2认同)