考虑以下课程
class test
{
public:
test(int x){ cout<< "test \n"; }
};
现在我想创建50个类test对象的数组。我无法改变课堂测试。
可以在堆或堆栈上创建对象。
在这种情况下,无法在堆栈上创建objs,因为我们在类
中没有默认构造函数test objs(1)[50]; /// Error...
现在我们可以考虑在这样的堆上创建obj ..
test ** objs = NULL;
objs = (test **) malloc( 50 * sizeof (test *));
for (int i =0; i<50 ; ++ i)
{
objs[i] = new test(1);
}
我不想使用malloc。还有其他方法吗?
如果你们想到更多解决方案,请发布它们......
答案 0 :(得分:7)
如果没有默认构造函数,则无法创建对象数组,如 Foo foo [N] 。这是语言规范的一部分。
执行:
test * objs [50];
for() objs[i] = new test(1).
您不需要malloc()。你可以声明一个指针数组。
c++decl> explain int * objs [50]
declare objs as array 50 of pointer to int
但你可能应该附加某种自动RAII型破坏。
OR 子类测试:
class TempTest : public test
{
public:
TempTest() : test(1) {}
TempTest(int x) : test(x) {}
TempTest(const test & theTest ) : test(theTest) {}
TempTest(const TempTest & theTest ) : test(theTest) {}
test & operator=( const test & theTest ) { return test::operator=(theTest); }
test & operator=( const TempTest & theTest ) { return test::operator=(theTest); }
virtual ~TempTest() {}
};
然后:
TempTest array[50];
您可以将每个 TempTest 对象视为 test 对象。
注意:operator =()&amp;复制构造函数不是继承的,因此必要时重新指定。
答案 1 :(得分:4)
为什么需要数组?
std::vector<test*> v(50);
或评论中建议的@j_random_hacker
:
std::vector<test> v(50, test(1));
一个例子:
/** g++ -Wall -o vector_test *.cpp && vector_test */
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
struct Test {
int value;
Test(int x) : value(x)
{
std::cout << "Test(" << value << ")" << " ";
}
operator int() const
{
std::cout << "int(" << value << ")" << " ";
return value;
}
};
int main()
{
using namespace std;
vector<Test> v(5, Test(1));
cout << endl;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
v[1] = 2;
v[2].value = 3;
cout << endl;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
输出:
Test(1)
int(1) 1 int(1) 1 int(1) 1 int(1) 1 int(1) 1
Test(2)
int(1) 1 int(2) 2 int(3) 3 int(1) 1 int(1) 1
答案 2 :(得分:3)
与许多人认为的相反,您实际上可以创建一个没有默认构造函数的对象数组。你不能做的是让它为所有构造函数的invokations使用一组参数。你只需要初始化它的所有元素。也就是说,您可以执行以下操作:
#define PRINTT(z, n, initializer) initializer
test objs[50] = {
BOOST_PP_ENUM(50, PRINTT, 1) // yields 1, 1, 1, .... 1
};
#undef PRINTT
这将使用1初始化所有50个元素。boost::pp
用于自动连续50次打印1
。
答案 3 :(得分:2)
我认为其他响应者也在字面上对待这个问题。
如果您真正想做的就是创建一个由50个对象组成的“组”,您可以将其视为一个数组,那么到目前为止,最简单,最易维护的方法是完成您要做的事情:
std::vector<test> objs(50, test(1));
这声明了vector
个50个对象,每个对象都是test(1)
的副本。 vector
基本上是C ++可扩展数组;虽然你可能不需要可生长性,但是可以使用2-arg构造函数调用它来复制构造每个元素这一事实在这里很有用。
你可以使用这个或多或少完全像一个数组 - 例如第五个元素是objs[4]
。性能也是一样的--C ++标准保证元素内部存储在连续的数组中。
答案 4 :(得分:0)
您不需要malloc()。您也可以使用new
作为指针数组:
test **objs = new test* [50];
答案 5 :(得分:0)
Boost的Pointer Container图书馆可能会来这里拯救。使用boost::ptr_vector<T>
,您可以保存堆分配的对象列表,这些对象甚至可以是多态的(虚函数),这对于std::vector<T>
来说是不可能的。
与std::vector<T>
不同,对象不会存储在后续的内存地址中。然而,调整容器大小的事情会更快,因为元素将保留其原始内存地址。最好的奖励是,您不需要自己调用delete
:当ptr_vector
超出范围时,包含的对象将被销毁。例如:
#include <boost/ptr_vector.hpp>
#include <iostream>
class test() {
protected:
int const i;
public:
explicit test(int i) : i(i) {}
virtual void who_am_i() const { std::cout << "I am test " << i << std::endl; }
};
class special_test : public test {
public:
explicit special_test(int i) : test(i) {}
virtual void who_am_i() const { std::cout << "I am special_test " << i << std::endl; }
};
int main() {
boost::ptr_vector<test> objs;
for (int i=0; i<50; ++i)
objs.push_back(new test(i)); // NB: constructing to heap here!
objs.push_back(new special_test(123)); // objs can also hold inherited classes
objs[13].who_am_i(); // outputs: I am test 13
objs[50].who_am_i(); // outputs: I am special_test 123
} // all created objects are automatically destroyed here