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

sam*_*sam 6 c#

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

string str="samplestring"; // this will allocate the space to hold the string
Run Code Online (Sandbox Code Playgroud)

在C#中,string是一个类类型,所以如果我们想要创建一个对象,通常我们必须使用该new关键字.那么如果没有new或如何发生分配constructors呢?

gor*_*ric 6

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

如果您愿意,可以通过任意数量的不同构造函数实例化字符串.例如:

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


Nik*_*hil 6

当你写作

string str="samplestring";
Run Code Online (Sandbox Code Playgroud)

编译器将生成两个指令:

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

注意,这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";
Run Code Online (Sandbox Code Playgroud)

此过程称为字符串实习.

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

例如,以下代码行:

string a = "abc";
string b = a + "xyz";
Run Code Online (Sandbox Code Playgroud)

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

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