12

字符串不变性是通过语句起作用,还是通过语句中的字符串起作用?

例如,我了解以下代码将在堆上分配两个字符串。

string s = "hello ";
s += "world!";

"hello" 将保留在堆上,直到垃圾收集;并且 s 现在引用“hello world!” 在堆上。但是,以下行在堆上分配了多少个字符串...1 或 2?另外,是否有工具/方法来验证结果?

string s = "goodbye " + "cruel world!";
4

9 回答 9

21

编译器对字符串连接有特殊处理,这就是为什么第二个例子只有一个字符串。而“实习”意味着即使你运行这条线 20000 次,仍然只有 1 个字符串。

重新测试结果......最简单的方法(在这种情况下)可能是查看反射器:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] string s)
    L_0000: ldstr "goodbye cruel world!"
    L_0005: stloc.0 
    L_0006: ldloc.0 
    L_0007: call void [mscorlib]System.Console::WriteLine(string)
    L_000c: ret 
}

如您所见 ( ldstr),编译器已经为您完成了这项工作。

于 2008-12-16T19:22:12.853 回答
3

文字字符串被实习,这意味着它"hello "不驻留在堆上,而是驻留在程序的数据段[参见注释]中(因此不符合垃圾收集的条件),同样适用于"world",因为"hello world"它也可能被实习,如果编译器足够聪明。

"goodbye cruel world" 被实习,因为字符串文字连接是编译器处理的东西。


编辑:我不确定数据段声明,请参阅此问题以获取更多信息。

于 2008-12-16T19:26:52.953 回答
0

实际上,可能 3. 一个 const 字符串表示“goodbye”,一个 const 字符串表示“cruel world”,然后一个新字符串表示结果。

您可以通过查看生成的代码来确定。这取决于编译器,(实际上,取决于语言,这并不明显)但您可以通过使用 -a 标志(我认为,查看手册页)来读取 g++ 的输出以获取中间代码.

于 2008-12-16T19:25:15.793 回答
0

不要相信你对字符串的“了解”。您可能会查看源代码以了解字符串的实现。例如你的例子:

string s = "goodbye " + "cruel world!";

在java中会分配一个字符串。Java 玩了一些非常可爱的技巧,而且很难被超越——除非你需要,否则永远不要优化!

然而,目前,据我所知,使用这个:

String s="";
for(int i=0;i<1000;i++)
    s+=" ";

创建一个 1000 个空格的字符串仍然往往效率极低

在循环中追加非常糟糕,但除此之外它可能与 StringBuilder 一样有效。

于 2008-12-16T19:26:00.083 回答
0

这里要小心,因为在编译时知道字符串值时,编译器可以进行一些非常不同的优化。如果您使用的字符串直到运行时才知道(从配置文件、数据库或用户输入中提取),您将看到一些非常不同的 IL。

于 2008-12-16T20:13:40.563 回答
0

如果您只是要做一两个字符串连接,我不会担心。

但是,如果你有很多连接,或者你有一个循环,那么你肯定要采取预防措施。在 Java 世界中,这意味着您使用 StringBuffer 而不是连接字符串。

于 2008-12-16T20:29:18.100 回答
0

如果不只是在一行中,则可以通过将第一个字符串放入 StringBuffer,进行连接并返回结果字符串来完成两个字符串的连接。

自己创建 StringBuffer 可能看起来有点矫枉过正,但无论如何都会发生这种情况。-

于 2008-12-16T20:44:05.167 回答
0

无论如何不要过早地优化,但不要低估字符串连接的性能有多差。这不是对象的创建,而是它导致的 GC 工作。

(ASP.NET 升级工程师)Tess Ferrnandez 的博客上有一个实验室,它展示了字符串连接如何使服务器瘫痪的(相当极端的,理所当然的)示例。

于 2008-12-16T21:05:48.323 回答
-1

如果编译器是“智能”的,它只会是一个带有“再见残酷世界!”的字符串。

于 2008-12-16T19:22:49.823 回答