String对象如何在没有new关键字或构造函数的情况下分配内存?

时间:2012-10-19 14:27:35

标签: c#

在C#中,如果我们想创建一个string类型的变量,我们可以使用:

string str="samplestring"; // this will allocate the space to hold the string

在C#中,string是类类型,因此如果我们要创建对象,通常我们必须使用new关键字。那么如何在没有newconstructors的情况下进行分配?

7 个答案:

答案 0 :(得分:6)

这只是C#编译器,通过允许字符串文字为您提供快捷方式。

如果您愿意,可以通过任意数量的constructors实例化字符串。例如:

 char[] chars = { 'w', 'o', 'r', 'd' };
 string myStr = new String(chars);

答案 1 :(得分:5)

写作时

string str="samplestring";

编译器将生成两条指令:

  1. 首先,ldstr从元数据中获取字符串文字;分配必要的内存量;创建一个新的String对象并将其引用推送到堆栈上。
  2. 然后stloc(或其中一个简短形式,例如stloc.0)将该引用存储在本地变量str中。
  3. 注意,ldstr只为每个字符序列分配一次内存。

    因此,在下面的示例中,两个变量都将指向内存中的同一对象:

    // CLR will allocate memory and create a new String object
    // from the string literal stored in the metadata
    string a = "abc";
    
    // CLR won't create a new String object. Instead, it will look up for an existing
    // reference pointing to the String object created from "abc" literal
    string b = "abc";
    

    此过程称为string interning

    另外,如您所知,在.NET中,字符串是不可变的。因此,在创建对象后,无法更改String对象的内容。也就是说,每次连接字符串时,CLR都会创建一个新的String对象。

    例如,以下代码行:

    string a = "abc";
    string b = a + "xyz";
    

    将编译成以下IL(当然不完全是):

    1. ldstr将分配内存并从String文字
    2. 创建新的"abc"对象
    3. stloc会将对象的引用存储在局部变量a
    4. ldloc会将该引用推送到堆栈
    5. ldstr将分配内存并从String文字
    6. 创建新的"xyz"对象
    7. call将调用堆栈中这些String个对象上的System.String::Concat
    8. System.String::Concat的呼叫将被分解为数十条IL指令和内部呼叫。简而言之,它将检查两个字符串的长度并分配必要数量的内存来存储连接结果,然后将这些字符串复制到新分配的内存中。
    9. stloc会将对新创建的字符串的引用存储在局部变量b

答案 2 :(得分:3)

根据MS文档,您不需要使用new命令来使用默认的字符串构造函数。

然而这确实有效。

char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);

c# Strings (from MSDN programming guide)

答案 3 :(得分:2)

字符串实际上是引用类型。变量保存对内存中值的引用。因此,您只是为对象分配引用而不是值。我建议你看一下Pluralsight的这个视频(你可以免费试用14天)

Pluralsight C# Fundamentals - Strings

免责声明:我与Pluralsight没有任何关系。我是订阅者,我喜欢那边的视频

答案 4 :(得分:1)

虽然一切都是.net中的对象,但仍然存在不需要实例化的原始类型(int,bool等)。 正如您所看到的here,字符串是一个4字节的地址ref,指向一个可以扩展到2GB的向量/数组结构。记住字符串是不可改变的类型,因此当您更改字符串时,您不是在编辑现有变量,而是为文字值分配新内存,然后将字符串指针更改为指向新的内存结构。 希望有所帮助

答案 5 :(得分:0)

当你使用文字创建一个字符串时,在内部,根据你的程序集标记有NoStringInterning标志,它看起来像:

String str = new String("samplestring");
// or with NoStringInterning
String str = String.Intern("samplestring");

答案 6 :(得分:-4)

在java中,如果你写这样的东西:

String s1 = "abc";
String s2 = "abc";

内存将在所谓的字符串池中为“abc”分配,s1和s2都将引用该内存。并且s1 == s2将返回true(“==”比较引用)。但如果你写:

String s1 = new String("abc");
String s1 = new String("abc");

s1 == s2将返回false。我想在c#中它会是一样的。