没有初始化的类中的数组

时间:2013-04-03 10:40:49

标签: c++ arrays class initialization

我一直在努力解决这个问题。在C ++中似乎非常无效,在A类中创建的B类数组必须由默认构造函数初始化。有没有办法避免这种行为?我实施了人员登记。如果我使用计数引用创建它,我会得到很多默认的构造函数调用,它似乎不太有效。另外,我必须创建不必要的默认构造函数。

4 个答案:

答案 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.