1

下面是我写的代码 Calc[] calculators = new Calc[10]; calculators[0].AddToSum(10);(对应的类和方法都写好了)。但是我得到“对象引用未设置为对象的实例”异常。然后通过一些研究,我通过执行以下操作删除了异常。

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;
4

6 回答 6

6

在 C# 中,有引用类型,也有值类型。类是引用类型。当你创建一个引用类型的变量时,你是在创建一个引用,而不是一个对象。引用的默认状态为空。如果您希望它引用一个对象,则必须使用 显式初始化它new,或者从另一个初始化的引用中分配 if。

C++ 没有这种区别。每种类型都是值类型(尽管您也可以创建对任何类型的引用)。当你创建一个值类型的变量时,你就是在创建一个对象。

于 2013-05-07T14:33:24.617 回答
1

在 new Calc[10] 中,您正在分配和调整数组大小。在 new Calc() 中,您正在创建实际的 Calc 对象

于 2013-05-07T14:23:14.790 回答
1

但是你会用这个语句得到同样的错误

Calc calc; 
calc.AddToSum(10);

在您分配值之前,对象为空。

Calc[] 计算器 = 新的 Calc[10]; 不分配。

根据 Benjamin (+1) 的回答,如果 Calc 是引用类型,它就可以工作。
你能把 Calc 做成一个结构吗?

于 2013-05-07T14:25:18.360 回答
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>();
于 2013-05-07T14:17:54.317 回答
0

当您在 C++ 中创建对象数组时,您会为每个对象的所有字段分配内存。因此,如果您的对象有两个整数字段,并且您创建了一个大小为 2 的数组,则会分配足够的内存来保存四个整数。

另一方面,在 c# 中,当您创建要创建的对象数组和引用数组(指向对象的指针)时。因此,除非您为每个引用分配内存(通过使用 new),否则您无法存储实例。

在 c++ 中同样的事情是创建一个指针数组,然后您必须实例化数组的每个元素。

于 2013-05-07T14:33:13.273 回答
-2

您的 C++ 代码也是错误的。在 C++ 中,您已经为 10 个 Calculator 对象分配了一个包含空间的数组。当您执行操作时,它会从该(未初始化的)内存中读取,获取一个值并将其添加到其中,然后将其写回。但是你有一个未初始化的对象开始。

它可能在 C++ 中有效,因为您有一个不需要调用构造函数的对象(计算器)。如果它有任何需要调用构造函数的初始化,它将不起作用。如果您要使用调试器并在 Calculator 构造函数中放置一个断点,您会发现它从未被调用过。

无论如何,要直接回答这个问题,这就是 C# 的工作方式。分配数组会为数组创建空间,但数组中的所有对象(假设对象类型)在分配之前都是空的。

可以这样想:我创建了一个数组来保存 X 类的 10 个对象。但是 X 有一个接受字符串的构造函数,我想为每个对象使用不同的字符串来调用它。如果不显式创建这 10 个对象中的每一个并将正确的字符串传递给每个构造函数,如何做到这一点?

于 2013-05-07T14:40:12.370 回答