对象创建差异

本文关键字:创建 对象 | 更新日期: 2023-09-27 18:04:22

两个语句之间的区别是什么

int main() 
{ 
    A a = new A();
    A a;
}

请解释这两个对象创建语句。

对象创建差异

第一个命令在堆栈上分配一个变量(A a(,并在堆上初始化(new A()(。

第二个只分配堆栈上的变量。它没有初始化,因此在通过函数的返回值或调用类构造函数进行赋值之前,不能使用它。


旁注:当你的程序被编译和运行时,它甚至与你写的代码完全不同。变量在您需要它们之前就已加载。上面的代码大致如下:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] class DERP.Program/A a,   // This code here declares a local
                                              // variable: A a;
           [1] class DERP.Program/A b)        // another local variable: A b;
   nop
   newobj     instance void DERP.Program/A::.ctor()  // This is: new A()
   stloc.1                           // this loads the new A() we created
                                     // into A b;  (stloc.1 means to store
                                     // the last item we created into the
                                     // local variable at index [1]
   ret
} // end of method Program::Main

如果你不完全理解每一个命令是什么,那也没关系,但我对它进行了评论,试图让它尽可能直截了当。由于我们从不将A a分配给任何东西,所以它只是放在本地堆栈上,挂在那里,什么也不做。我们不能使用它,因为它没有指向任何对象。


在代码中,您可能会看到声明与实际赋值分离,这有很多不同的原因。

例如,有时您需要在try {} catch {}子句之外声明一个变量。假设您的类在其构造函数中取一个值。您有一个函数可以获取数据,比如从数据库中获取数据。但是,由于它是一个DB调用,您希望捕获异常,如果抛出异常,则使用默认值初始化类,而不是使用DB调用的返回值。

由于作用域在C#中的工作方式,在try {} catch {}内部声明的变量在其外部是不可访问的,因此在初始化变量之前,您需要在代码中较早地声明变量。

A a = new A();

这将创建一个类型为A的新对象。a的值将是A的新实例。

A a;

这只会将声明为A的类型。a的值将为null

第一个创建一个新的贪得无厌,并将其分配给变量a

第二个不创建任何实例,所以a就是null

在第一条语句中,它将创建一个类的新对象实例,并将其分配给变量

在第二个语句中,它只是在创建一个引用。

只有您的第一条语句真正创建了一个新对象。其他人提到的第二个只是在堆栈上分配一个类型为a的变量。

第一个在托管堆上创建一个新对象,并将其上的引用存储在堆栈上创建的CCD_。