内存中字符串对象的总数
本文关键字:对象 字符串 内存 | 更新日期: 2023-09-27 18:13:22
谁能告诉我在内存中创建的字符串实例的总数为下面的例子?如能简短解释,不胜感激。
我代码: String A = "1" + "2" + "3" ; /* total number of strings in memory = ?? */
String B = "1" + "2" + "1" ; /* total number of strings in memory = ?? */
string one = "1";
string two = "2";
string three = "3";
String C = one + two + three; /* total number of strings in memory = ?? */
String D = one + two + one; /* total number of strings in memory = ?? */
来自c#字符串连接的文档:
当使用+操作符连接字符串字面值或字符串常量时,编译器将创建单个字符串。没有运行时串联发生。
这意味着您的连接每次只创建一个字符串,因此您的示例在内存中总共产生7个字符串:
String A = "1" + "2" + "3" ; // 1 (concatenation of literals)
String B = "1" + "2" + "1" ; // 1 (concatenation of literals)
string one = "1"; // 1
string two = "2"; // 1
string three = "3"; // 1
String C = one + two + three; // 1 (concatenation of string constants)
String D = one + two + one; // 1 (concatenation of string constants)
// = 7 strings in total
但是,如果在循环中进行连接,则会生成更多字符串,例如:
for word in text:
result_string += word // Bad! Creates a new string in each iteration
在这种情况下,最好使用StringBuilder.append
:
System.Text.StringBuilder builder = new System.Text.StringBuilder();
for word in text:
builder.Append(word) // Good! Just appends to the string builder
让我们看看IL DASM中的代码IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 54 (0x36)
.maxstack 3
.locals init ([0] string A,
[1] string B,
[2] string one,
[3] string two,
[4] string three,
[5] string C,
[6] string D)
IL_0000: nop
IL_0001: ldstr "123"
IL_0006: stloc.0
IL_0007: ldstr "121"
IL_000c: stloc.1
IL_000d: ldstr "1"
IL_0012: stloc.2
IL_0013: ldstr "2"
IL_0018: stloc.3
IL_0019: ldstr "3"
IL_001e: stloc.s three
IL_0020: ldloc.2
IL_0021: ldloc.3
IL_0022: ldloc.s three
IL_0024: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0029: stloc.s C
IL_002b: ldloc.2
IL_002c: ldloc.3
IL_002d: ldloc.2
IL_002e: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_0033: stloc.s D
IL_0035: ret
} // end of method Program::Main
如你所见,有5个字符串常量
"123", "121", "1", "2", "3"
和两个通过连接获得的字符串。总7 .
虽然A和C (B和D)字符串是相同的,但它们在内存中是不同的实例。
To Arghya C.
如果应用不安全代码并更改变量A的值:
Console.WriteLine(A + " " + C);
fixed (char* p = A)
{
p[1] = 'x';
}
Console.WriteLine(A + " " + C);
我们得到以下输出:
123年123
x3 123
可以看到,只有变量A发生了变化,而C变量的值保持不变。这证明它们是不同的副本。
但是,如果我们这样写:
String A = "1" + "2" + "3";
String C = "123";
执行上面的不安全代码后,我们得到以下结果:
123年123
1 x3 x3
也就是说,在本例中,变量A和C保持了对同一个字符串实例的引用。
一开始我写了错误的答案,因为我认为编译器足够聪明,可以在编译时理解String C = one + two + three;
连接常量并将在同一字符串上创建引用。