为什么不能在C ++中动态声明一个对象数组,如下所示:

时间:2014-06-17 03:13:32

标签: c++ arrays dynamic-arrays

在我的C ++项目中,有一个类需要创建一个对象数组。 在类的不同实例之间,数组的大小将不同,这就是我选择使用数组的原因。

如果我这样做:

int numberOfPlayers; // This is determined at run time.
int *players; 

//In constructor
players= new int[numberOfPlayers]; // This works

但如果我这样做:

Character *players;
players = new Character[numberOfPlayers]; // Compiler complains

编译器抱怨"没有匹配的构造函数用于初始化Character"

如何动态声明类型"字符"。

的数组

注意:角色与char无关。 Character是我自己创建的一个类的名称。

编辑:字符没有默认构造函数,因为它需要传递几个参数,因此可以使用正确的状态进行初始化。唯一的构造函数有几个参数。

编辑:我在一个向量上选择了一个动态创建的数组,因为我知道在实例的生命周期中,数组的大小将是常量,尽管在不同的实例之间,大小会有所不同。我认为这对性能原因(内存/速度)有意义。

6 个答案:

答案 0 :(得分:8)

“正确”的方式是使用std::vector。它是一种快速,安全,更强大的替代恐怖new

std::vector<Character> vec;
vec.push_back(Character(params));
vec.push_back(Character(other_params));

如果您知道提前的大小,则可以使用std::vector::reserve

来避免重新分配开销
std::vector<Character> vec;
vec.reserve(50);
vec.push_back(Character(params));
vec.push_back(Character(other_params));

std::vector的开销几乎不存在。

现在,你不能按照自己的方式做到这一点,这是因为默认情况下new使用默认构造函数,它不存在。

答案 1 :(得分:4)

问题是您的类型Character没有定义表单的默认构造函数:

Character::Character()
{
   // etc.
}

答案 2 :(得分:3)

您的类型需要默认构造函数。与C malloc不同,operator new在分配时为您构造实例。然后它需要一个无参数(默认)构造函数,因为它无法传递参数。所以......

class Character
{
public:
    Character(){}
};

答案 3 :(得分:3)

&#34;字符没有默认构造函数,因为它需要传递几个参数,因此可以使用正确的状态进行初始化。唯一的构造函数有几个参数&#34;

然后数组是错误的类型,因为数组总是默认构造其成员。

使用:

std::vector<Character> players;

大小可以根据需要变化,并且每个角色构建完成后你可以call players.push_back( character )

答案 4 :(得分:2)

简短的回答是,你不能这样做,因为标准不允许这样做。没有任何技术原因无法被允许 - 它只是不是。

一些编译器(例如gcc)多年来一直支持它作为C ++的扩展。它已经被各种编译器在C中支持了足够长的时间,C99对它进行了标准化,因此所有(当前合理的)C编译器现在都支持它。

有人提议添加类似数组的类,其大小在创建时确定,并在此之后保持不变,但委员会决定不接受 1 。只留下std::array,这需要在编译时确定的大小,std::vector,其大小可以在运行时动态变化。

但是,公平地说,如果您在创建矢量时知道矢量的大小,则可以在创建时指定矢量大小。虽然它仍然能够调整自身,但该功能主要在resizepush_back。如果您只是不使用它们,那么使用std::vector与本机阵列相比的开销通常非常小,因此您不太可能从其他技术中获得显着收益(可能除外)在相当模糊的情况下)。


1.至少IMO,这是正确的决定 - 虽然我可以看到想法背后的基本推理,但我认为该提案存在足够的缺陷,以至于没有它我们会更好。 功能

答案 5 :(得分:1)

因为分配Character数组意味着该数组将包含一定数量的Character个实例。分配数组时,必须以某种方式初始化包含的每个实例,并且需要默认构造函数。

你必须声明Character::Character() { }让编译器调用它。如果您不能提供默认构造函数,那么您应该考虑使用Character**,以便您可以根据需要初始化它们,例如:

Character **array = new Character*[amount];
array[0] = new Character(...);

请注意,这需要删除每个实例,因此您需要

而不是delete[] array
for (int i = 0; i < amount; ++i)
  delete array[i];
delete [] array;

另一种方法是忘记数组并使用std::vector

vector<Character> character;
character.push_back(Character(...));

这也可以减轻你自己管理记忆的需要。