需要帮助创建一个对象数组

时间:2009-05-11 21:21:03

标签: c++

我正在尝试使用整数参数创建一个类对象数组。我看不出这个简单的小代码有什么问题。有人可以帮忙吗?

#include <fstream>
#include <iostream>
using namespace std;

typedef class Object
{
 int var;
public:
 Object(const int& varin) : var(varin) {}
} Object;

int main (int argc, char * const argv[])
{
 for(int i = 0; i < 10; i++)
 {
  Object o(i)[100];
 }

 return 0;
}

3 个答案:

答案 0 :(得分:8)

在C ++中,typedef es和class s不需要struct。所以:

class Object
{
 int var;
public:
 Object(const int& varin) : var(varin) {}
};

此外,描述性名称总是可取的,Object被滥用了。

int main (int argc, char * const argv[])
{
 int var = 1;

 Object obj_array[10]; // would work if Object has a trivial ctor

 return 0;
}

否则,在您的情况下:

int main (int argc, char * const argv[])
{
 int var = 1;

 Object init(var);
 Object obj_array[10] = { var, ..., var }; // initialize manually

 return 0;
}

但是,你真的应该寻找vector

#include <vector>
int main (int argc, char * const argv[])
{
 int var = 1;

 vector<Object> obj_vector(10, var); // initialize 10 objects with var value

 return 0;
}

答案 1 :(得分:4)

dirkgently的破坏是C ++中项目数组的相当准确的表示,但是他正在用相同的值初始化数组中的所有项目,看起来你试图用不同的值初始化每个项目。

要回答您的问题,请创建一个带有int构造函数参数的对象数组。你不能,在分配数组时创建对象,并且在没有普通构造函数的情况下,编译器会抱怨。但是你可以初始化一个指向你对象的指针数组,但你真的可以通过向量获得更多的灵活性,所以我的下面的例子将使用std :: vector。

如果您希望每个Object具有不同的值,则需要单独初始化每个对象,您可以使用以下两种方法之一;在堆栈上,或在堆上。让我们先看看堆栈。

任何采用单个参数且未标记为explicit的构造函数都可以用作隐式构造函数。这意味着,在期望该类型的对象的任何地方,您可以改为使用单个参数类型的实例。在这个例子中,我们创建一个Object类的向量并向其添加100个对象(push_back将项添加到向量),我们将一个整数传递给push_back,它隐式地创建一个传递整数的Object。

#include <vector>
int main() {
    std::vector<Object> v;

    for(int i = 0; i < 100; i++) {
        v.push_back(i);
    }
}

或明确说明:

#include <vector>
int main() {
    std::vector<Object> v;

    for(int i = 0; i < 100; i++) {
        v.push_back(Object(i));
    }
}

在这些示例中,所有Object对象都在for循环范围内的堆栈上分配,因此当对象被推入向量时会发生复制。复制大量对象可能会导致一些性能问题,尤其是当您的对象复制成本很高时。

解决此性能问题的一种方法是在堆上分配对象并存储指向向量中对象的指针:

#include <vector>
int main() {
    std::vector<Object*> v;

    for(int i = 0; i < 100; i++) {
        v.push_back(new Object(i));
    }

    for(int i = 0; i < 100; i++) {
        delete v[i];
    }
}

由于我们的对象是在堆上创建的,我们需要确保删除它们以调用它们的解构函数,并释放它们的内存,这个代码在第二个循环中执行。

手动调用delete有自己的注意事项,如果你将这些指针传递给其他代码,你可以快速找到谁拥有指针以及谁应该删除它们。解决此问题的一种更简单方法是使用智能指针来跟踪指针的生命周期,请参阅boost::shared_ptrtr1::shared_ptr作为引用计数指针:

#include <vector>
int main() {
    std::vector<shared_ptr<Object> > v;

    for(int i = 0; i < 100; i++) {
        Object* o = new Object(i);
        v.push_back(shared_ptr<Object>(o));
    }
}

您会注意到shared_ptr构造函数是显式的,这是故意完成的,以确保开发人员有意将其指针填充到共享指针中。当释放对对象的所有引用时,shared_ptr将自动删除该对象,从而使我们无需担心它的生命周期。

答案 2 :(得分:0)

如果您想坚持使用数组,则必须手动初始化或使用默认构造函数。但是,您可以通过使用默认参数创建构造函数来获得某些控制。这将被编译器视为默认构造函数。例如,以下代码按顺序打印出数字0,...,9。 (但是,我不确定标准是否必须按顺序构造数组中的对象。它可能依赖于实现,在这种情况下,数字可能以任意顺序出现。)

#include <iostream>

using namespace std;

struct A {
   int _val;

   A(int val = initializer()) : _val(val) {}

   static int initializer() { static int v = 0;  return v++; }
};

int main()
{
   A a[10];
   for(int i = 0; i < 10; i++)
      cout << a[i]._val << endl;
}