以下是我写的代码
Calc[] calculators = new Calc[10];
calculators[0].AddToSum(10);
(编写相应的类和方法)。
但我得到了#34;对象引用未设置为对象的实例"然后通过一些研究我通过以下方式删除了异常。
for (int i = 0; i < 10; i++)
{
calculators[i] = new Calc();
}
有人可以解释为什么我们需要再次分配内存,这与c / c ++不同。 这就是我在c ++中的表现:
Calculator *calc=new Calculator[10]//I know I need to check for std::bad_alloc exception
calculators[0].AddToSum(10);
delete[] calc;
答案 0 :(得分:5)
在C#中,有引用类型,并且有值类型。类是引用类型。创建引用类型的变量时,您将创建引用,而不是对象。引用的默认状态为null。如果您希望它引用一个对象,则必须使用new
显式初始化它,或者从另一个初始化引用中指定if。
C ++没有这种区别。每种类型都是值类型(尽管您也可以创建对任何类型的引用)。创建值类型的变量时,您将创建一个对象。
答案 1 :(得分:1)
在新的Calc [10]中,您正在分配和调整数组大小。在新的Calc()中,您正在创建实际的Calc对象
答案 2 :(得分:1)
但你会在这句话中得到同样的错误
Calc calc;
calc.AddToSum(10);
在您指定值之前,对象为空。
Calc [] calculators = new Calc [10];不分配。
基于本杰明(+1)的答案,如果Calc是参考类型,它就有效 你能让Calc成为一个结构吗?
答案 3 :(得分:0)
我不认为你再次分配内存,但你仍然需要为calculators[0]
实例化一些值。
在您的第一个代码段中,您尝试在.AddToSum
的值上调用Null
。
Ps:您可以执行以下操作,从头开始初始化每个Calc
:
Calc[] calculators = new Calc[10]{
new Calc(),
new Calc(),
...,
// Repeat 10 times to match array length
};
更新:回应以下评论;好的,试试这个:
calc[] calculators = Enumerable.Repeat(new Calc(), 127).ToArray<Calc>();
答案 4 :(得分:0)
在c ++中创建对象数组时,为每个对象的所有字段分配内存。因此,如果您的对象有两个整数字段并且您创建了一个大小为2的数组,则会分配足够的内存来容纳四个整数。
另一方面,在c#中创建一个正在创建的对象数组和引用数组(指向对象的指针)。因此,除非为每个引用分配内存(使用new),否则无法存储实例。
c ++中的同样的事情是制作一个指针数组,然后你必须实例化数组的每个元素。
答案 5 :(得分:-2)
您的C ++代码也是错误的。 在C ++中,您已经为10个Calculator对象分配了一个包含空格的数组。 当你进行操作时,它从那个(未初始化的)内存中读取,抓取一个值,然后添加它,然后将其写回。 但是你有一个未初始化的对象可以从中开始。
它可能在C ++中有效,因为你有一个不需要调用构造函数的对象(Calculator)。如果它有任何初始化需要调用构造函数,它将无法工作。如果您要使用调试器并在Calculator构造函数中放置断点,您将看到它从未被调用过。
无论如何,要直接回答这个问题,这就是C#的工作方式。分配数组会为数组创建空间,但是数组中的所有对象(假设对象类型)在它们自己分配之前都是空的。
这样想:我创建一个数组来保存10个X类对象。但是X有一个构造函数,它接受一个字符串,我想用每个对象的不同字符串调用它。如果没有明确地创建这10个对象中的每一个并将正确的字符串传递给每个构造函数,人们将如何这样做?