【问题标题】:C# How to store a stringC#如何存储字符串
【发布时间】:2014-04-05 10:24:35
【问题描述】:

我想了解“Hello World”之类的字符串值存储在哪里或如何存储。

例如:

示例 1:

radLabel1.Text = "Hello";
radLabel2.Text = "Hello";
radLabel3.Text = "Hello";

示例 2:

string strTemp = "Hello";
radLabel1.Text = strTemp;
radLabel2.Text = strTemp;
radLabel3.Text = strTemp;

我知道第二种方法最有用,我正在这样做,但我想知道示例 1 的字符串是如何存储在 RAM 中的。我认为虽然它们是相同的,但在 RAM 中为它们创建了三个位置来存储它们。但是在示例 2 中,仅为示例 2 的字符串创建了一个位置,并使用其地址进行访问。我对吗 ?你能解释一下这个或在 RAM 中存储变量吗?

【问题讨论】:

  • 字符串被保留,这就是您要查找的术语。在您的代码中,只有一份"Hello" 存储在内存中。见this wikipedia article
  • 字符串的几个字节不算什么,因为大多数机器都有很多 GB 的 RAM。如果你想优化你的程序,这里不是地方。另外,请阅读有关字符串实习的信息。见Why only literal strings saved in the intern pool by default?。您的第二个示例“最有用”的原因是,如果您想将 "Hello" 更改为 "Goodbye",您只需在一个地方进行。
  • 字符串是 intern 的,即如果它们具有相同的值,则只有一个副本存储在内存中。对于 RAM 中的字符串,Why Hackers Love String Data Type 读起来很有趣。

标签: c#


【解决方案1】:

常用的术语是字符串字面量是“实习的”。这是一个毫无意义的术语,并不能很好地描述真正发生的事情。

.NET 程序集包含两个数据块,元数据和 IL。元数据主要用于描述程序集中的类型并包含资源。 IL 是您编写的代码,翻译成中间语言格式。

元数据部分有 5 个表,其中之一称为“字符串表”。高度描述了它包含的内容,这就是您的“Hello”字符串的存储位置。它的格式已经与通常将字符串存储在垃圾收集堆中的方式相同,但在对象标头中有一个额外的标志,表明它是一个字符串文字,而不是存储在堆中。

程序集内容通过内存映射文件映射到虚拟内存,与 .NET System.IO.MemoryMappedFiles.MemoryMapFile 类完全相同。 strTemp 对象引用将由抖动发出的单个 MOV 指令初始化,并存储一个指针,该指针直接指向文件映射视图中的字符串表条目。当您的程序第一次实际使用字符串内容时,操作系统页面错误会确保字符串存在于 RAM 中。

垃圾收集器在执行收集时会找到 strTemp 对象引用。但是只会忽略引用,对象头中的标志说它应该因为字符串对象实际上并没有存储在垃圾收集堆中。这就是“实习”的真正含义。

【讨论】:

    【解决方案2】:

    我认为虽然它们是相同的,但创建了三个地方 将它们存储在 RAM 中。

    字符串被保留

    当它们是相同的字符串常量时,只保留一个副本。这意味着在您的第一个示例中只有一个“Hello”。

    【讨论】:

      【解决方案3】:

      在示例 2 中,您在第一行创建了一个字符串。然后,您只需将 reference 传递给这 3 个标签。正如您所说,它仍然是内存中的单个对象。但是,由于字符串在 C# 中是不可变的,因此将新字符串分配给 radLabel2.Text 不会更改其他字符串的值,而是会创建一个新字符串。

      【讨论】:

        【解决方案4】:

        当你声明时

           radLabel1.Text="Hello";
        

        它在内存中的某处创建一个值为 Hello 的临时字符串,并将该值传递给 radLabel.text 。对于 radLabel2.Text 和 radLabel3.text,程序仍然创建 temp 2 和 temp 3 来存储“Hello”。因为没有什么可以告诉程序它们是相同的。

        但是,当你声明时

           string strTemp = "Hello";
        

        它在内存中创建一个字符串(当然),但与“Hello”不同。因为他们为它创建了一个名称。这项工作就像您计算机的桌面快捷方式。所以当你使用它时,你只是调用了快捷方式,它绕过了创建新字符串的过程,因为值已经定义了。

        希望你理解

        【讨论】:

          猜你喜欢
          • 2017-11-30
          • 1970-01-01
          • 2012-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-01
          • 2011-12-29
          • 2012-07-12
          相关资源
          最近更新 更多