gpt4 book ai didi

c# - 在 .Net 中获取子字符串时,新字符串是引用相同的原始字符串数据还是复制数据?

转载 作者:可可西里 更新时间:2023-11-01 08:00:57 24 4
gpt4 key购买 nike

假设我有以下字符串:

string str1 = "Hello World!";  
string str2 = str1.SubString(6, 5); // "World"

我希望在上面的例子中 str2 不会复制“World”,而只是最终成为一个指向相同内存空间的新字符串,只是它以偏移量 6 开头长度为 5。

实际上,我正在处理一些可能非常长的字符串,出于性能原因,我对它在幕后的工作方式很感兴趣。我对 IL 不太熟悉,无法对此进行调查。

最佳答案

正如其他人所指出的,CLR 在执行子字符串操作时会进行复制。

正如您所注意到的,字符串当然可以表示为具有长度的内部指针。这使得子串操作极其便宜。

还有一些方法可以降低其他操作的成本。例如,可以通过将字符串表示为子字符串树来降低字符串连接的成本。

在这两种情况下,这里发生的是操作的结果实际上并不是“结果”本身,而是一个廉价的对象,它代表了在需要时获得结果的能力。

细心的读者可能刚刚意识到这就是 LINQ 的工作原理。当我们说

var results = from c in customers where c.City == "London" select c.Name;

“结果”包含查询结果。此代码几乎立即返回; results 包含一个对象,表示查询。只有当查询被迭代时,搜索集合的昂贵机制才会启动。我们使用序列语义的一元表示的力量将计算推迟到以后。

然后问题就变成了“在字符串上做同样的事情是个好主意吗?”答案是响亮的“不”。我对此进行了大量痛苦的现实世界实验。我曾经花了一个夏天重写 VBScript 编译器的字符串处理例程,以将字符串连接存储为字符串连接操作树;只有当结果实际用作字符串时,连接才会真正发生。这是灾难性的;跟踪所有字符串指针所需的额外时间和内存使得 99% 的情况——有人做一些简单的小字符串操作来呈现网页——慢了大约两倍,同时大大加快了极少数人的速度使用朴素的字符串连接编写的页面。

.NET 程序中绝大多数实际的字符串操作都非常快;它们编译成内存移动,这些移动在正常情况下会很好地保留在处理器缓存的内存块中,因此速度非常快。

此外,对字符串使用“内部指针”方法会使垃圾收集器变得相当复杂;采用这种方法似乎会使 GC 整体变慢,这对任何人都没有好处。您必须查看更改影响的总成本,而不仅仅是它对某些狭窄场景的影响。

如果您由于异常大的数据而有特定的性能需求,那么您应该考虑编写自己的专用字符串库,该库使用像 LINQ 那样的“一元”方法。您可以在内部将您的字符串表示为 char 数组,然后子字符串操作只需复制对数组的引用并更改开始和结束位置。

关于c# - 在 .Net 中获取子字符串时,新字符串是引用相同的原始字符串数据还是复制数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2473816/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com