我一直在努力解决这个问题。在C ++中似乎非常无效,在A类中创建的B类数组必须由默认构造函数初始化。有没有办法避免这种行为?我实施了人员登记。如果我使用计数引用创建它,我会得到很多默认的构造函数调用,它似乎不太有效。另外,我必须创建不必要的默认构造函数。
答案 0 :(得分:1)
当您创建对象数组时,无论是静态数组(Person people[1000]
)还是动态分配(Person* people = new Person[1000]
),都将使用默认构造函数创建和初始化所有1000个对象。
如果要为对象创建空间,但尚未创建它们,可以使用像std::vector这样的容器(实现动态大小的数组),或使用指针数组,如{ {1}}或Person* people[1000]
- 在这种情况下,您可以使用Person** people = new Person*[1000]
初始化所有项目以指示空记录,然后逐个分配对象:NULL
,但您也可以记住每个对象people[i] = new Person(/* constructor arguments here */)
。
答案 1 :(得分:1)
我想我有你想要的解决方案。我在GCC 4.6上进行了测试,可能需要修改MSVC ++的对齐位,但这里是示例输出和源代码:
源代码(使用GCC 4.6测试):
#include <cstdio>
#include <cstring>
#include <new>
// std::alignment_of
template <typename T, std::size_t capacity>
class StaticVector
{
public:
StaticVector() : _size(0)
{
// at this point we've avoided actually initializing
// the unused capacity of the "static vector"
}
~StaticVector()
{
// deconstruct in reverse order of their addition
while (!empty())
pop_back();
}
void push_back(const T &src)
{
// at this point we initialize the unused array entry by copy
// constructing it off the passed value
new (data() + _size) T(src);
_size++;
}
void pop_back()
{
_size--;
// we manually call the deconstructor of the entry we are marking as unused
data()[_size].~T();
}
bool empty() const {return _size == 0;}
std::size_t size() const {return _size;}
// NOTE: you'd better index only into constructed data! just like an std::vector
T & operator[](int i) {return *data()[i];}
const T & operator[](int i) const {return *data()[i];}
T * data() {return reinterpret_cast<T*>(_data);}
const T * data() const {return reinterpret_cast<const T*>(_data);}
protected:
// NOTE: I only tested this on GCC 4.6, it will require some
// conditional compilation to work with MSVC and C++11
#if 1 // for GCC without c++11
char _data[sizeof(T[capacity])] __attribute__((aligned(__alignof__(T))));
#else // UNTESTED: The C++11 way of doing it?
alignas(T) char _data[sizeof(T[capacity])]; // create a suitable sized/aligned spot for the array
#endif
std::size_t _size;
};
// NOTE: lacks a default constructor, only
// constuctor that takes parameters
class B
{
public:
B(int param1, const char param2[])
{
printf("Constructing B at %08X with parameters (%i, %s)\n", (int)this, param1, param2);
x = param1;
strcpy(buffer, param2);
}
~B()
{
printf("Deconstructing B at %08X\n", (int)this);
}
// NOTE: only provided to do the printf's, the default
// copy constructor works just fine
B(const B &src)
{
printf("Copying B from %08X to %08X\n", (int)(&src), (int)this);
x = src.x;
memcpy(buffer, src.buffer, sizeof(buffer));
}
protected:
int x;
char buffer[128];
};
class A
{
public:
StaticVector<B, 8> staticVectorOfB;
};
int main()
{
printf("PROGRAM START\n");
A a;
a.staticVectorOfB.push_back(B(0, "Uno"));
a.staticVectorOfB.push_back(B(1, "Dos"));
a.staticVectorOfB.push_back(B(2, "Tres"));
printf("PROGRAM END\n");
return 0;
}
示例输出:
PROGRAM START
Constructing B at 0022FDC4 with parameters (0, Uno)
Copying B from 0022FDC4 to 0022F9A0
Deconstructing B at 0022FDC4
Constructing B at 0022FE48 with parameters (1, Dos)
Copying B from 0022FE48 to 0022FA24
Deconstructing B at 0022FE48
Constructing B at 0022FECC with parameters (2, Tres)
Copying B from 0022FECC to 0022FAA8
Deconstructing B at 0022FECC
PROGRAM END
Deconstructing B at 0022FAA8
Deconstructing B at 0022FA24
Deconstructing B at 0022F9A0
答案 2 :(得分:0)
首先,您不需要创建默认构造函数,因为否则编译器将生成其代码。我不认为有一种干净的方法可以避免在对象上调用默认构造函数(也许优化器会将其剥离出来用于数组),但肯定会有一个脏的:
class B
{
};
class A
{
private:
char _array[sizeof(B)*5];
B* getB() {return (B*)_array;}
};
然后你仍然可以像使用固定大小的数组一样使用指针。 sizeof
并且递增/递减将不起作用。
我想你不应该被默认构造函数的“低效率”打扰太多。他们是有原因的。否则,如果默认构造函数确实没有工作要做,那么它应该内联,然后它不会产生执行开销。
答案 3 :(得分:0)
阵列怎么样,A里面是B级?是不是B arr [size];?而是使用向量,以便您可以在初始化中初始化大小,然后推送对象。或者像下面这样的新动态数组。 initfunc可以创建您的注册。由于initfunc是在构造函数的初始化中调用的,因此效率很高。
B级 { };
class A
{
B *barray;
B* initfunc()
{
B* tmp = new B[5];
//init elements of B
return tmp;
}
public:
A():barray(initfunc())
{
}
~A()
{
delete[] barray;
}
};
//the code is not exception safe, vector recommended.