0

コンストラクターを呼び出さずにスタックにクラスの配列を割り当てたいと思います。次の例で明確にします。

template<class t,int SetNum> class set
{
private:
    t Storage[SetNum];
};

class myClass
{
private:
    int* Array;
public:
    myClass()
    {
        Array=new int[10];
    }
}
int main()
{
    set<myClass,10> Set;
}

のコンストラクターが呼び出されArrayたときに発生する10 個の新しい int を割り当てたくありませんが、 に割り当てられたスペースが必要です。myClassmyClass

4

1 に答える 1

1

unsigned char要素の「バッキング ストレージ」として使用する s (またはそのようなもの) の配列が必要です。次に、配置new演算子 (たとえばhereを参照) を呼び出して、そこにインスタンスを構築する必要があります (ちなみに、これはstd::vector既に行っていることです)。 )。

警告:プレースメント new を使用する場合は、作成したオブジェクトの割り当てを手動で解除する責任があり、明示的にデストラクタを呼び出します。また、placement new に渡すポインタは、作成しているオブジェクトに対して適切に配置する必要があります。そうしないと、問題が発生する可能性があります。

この質問も参照してください。


説明されているテクニックを組み合わせstd::arrayてビルドした例 (このトリックを機能させるstd::vectorには C++11 が必要です):union

#include <cstddef>
#include <memory>
#include <stdexcept>
#include <iostream>

template<typename T, std::size_t N>
class array_noinit
{
    union storage_helper
    {
    private:
        // this member assures that the storage is properly aligned
        T t;
    public:
        unsigned char storage[sizeof(T)*N];

        // needed because T's constructor/destructor is implicitly deleted
        storage_helper() { };
        ~storage_helper() { };
    };

    storage_helper s;

    std::size_t _size;
    T * _storage;
public:
    array_noinit() :
        _size(0), _storage((T*)s.storage)
    {}

    ~array_noinit()
    {
        while(_size>0)
            pop_back();
    }

    void push_back(const T & elem)
    {
        if(_size>=N)
            throw std::runtime_error("Not enough capacity.");
        new(_storage+_size) T(elem);
        _size++;
    }

    void pop_back()
    {
        if(_size>0)
        {
            _size--;
            _storage[_size].~T();
        }
    }

    T & at(std::size_t Idx)
    {
        if(Idx>=_size)
            throw std::out_of_range("Idx out of range.");
        return _storage[Idx];
    }

    std::size_t size() const
    {
        return _size;
    }

    std::size_t capacity() const
    {
        return N;
    }
};

class A
{
    int _i;
public:
    A(int i) : _i(i)
    {
        std::cout<<"In A constructor - "<<_i<<"\n";
    }

    A(const A & right)
        : _i(right._i)
    {
        std::cout<<"In A copy constructor - "<<_i<<"\n";
    }

    ~A()
    {
        std::cout<<"In A destructor - "<<_i<<"\n";
    }
};

int main()
{
    std::cout<<"With ints\n";
    array_noinit<int, 4> arr;
    arr.push_back(1);
    arr.push_back(2);
    arr.push_back(3);
    arr.push_back(4);

    for(std::size_t i=0; i<4; i++)
        std::cout<<arr.at(i)<<" ";
    std::cout<<"\n";

    std::cout<<"With a class - we don't add anything\n";
    array_noinit<A, 10> arr2;

    std::cout<<"With a class - now we add stuff\n";
    array_noinit<A, 10> arr3;
    arr3.push_back(A(1));
    arr3.push_back(A(2));
    arr3.push_back(A(3));
    return 0;
}

出力:

With ints
1 2 3 4 
With a class - we don't add anything
With a class - now we add stuff
In A constructor - 1
In A copy constructor - 1
In A destructor - 1
In A constructor - 2
In A copy constructor - 2
In A destructor - 2
In A constructor - 3
In A copy constructor - 3
In A destructor - 3
In A destructor - 3
In A destructor - 2
In A destructor - 1

Edit整列された storage を取得するための。

于 2012-10-23T00:25:11.317 に答える