对象创建差异
本文关键字:创建 对象 | 更新日期: 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_。