2012-10-23 2 views
0

생성자를 호출하지 않고 스택에 클래스를 할당하고 배열하려고합니다. 다음 예제 clarifys는 :비 초기화 클래스 배열

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; 
} 

나는 myClass의 생성자를 호출 할 때 발생 Array의 10 새의 int를 할당 할,하지만 여전히 myClass에 할당 된 공간을 원하지 않는다.

+0

질문이 모호합니다. myClass 배열이나 int 배열을 할당하지 않겠습니까? – garbagecollector

+1

개체 배열을 생성하면 자동으로 기본 생성자가 호출됩니다. 이것을 피할 방법이 없습니다. 기본 생성자를 호출하지 않아도된다고 생각하는 부분에서 무엇을하려고합니까? –

+0

@DumpHole 질문에 명확하게 "myClass의 생성자가" –

답변

1

게재 위치 new 오퍼레이터 호출 다음 요소 "백업 저장"으로 사용하고 unsigned char들 (또는)의 배열을 가지고있다 (이 인스턴스를 생성하기 위해 (예 here 참조)하는 바이 방법은 std::vector가 이미 수행하는 것입니다.)

경고 : 새로운 배치를 사용하는 경우 명시 적으로 소멸자를 호출, 수동으로 당신이 그것으로 만든 객체의 할당을 해제 할 책임이있다; 또한 새 배치에 전달하는 포인터는 작성중인 객체에 대해 올바르게 정렬되어야합니다. 그렇지 않으면 잘못된 요소가 발생할 수 있습니다.

this question도 참조하십시오.

#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 
설명하는 기술로 구축 std::arraystd::vector의 트위스트 믹스의


예 (일할 수있는 union 해트트릭을 C++ (11) 필요)


Edi tmuch simpler way to get aligned storage이 있습니다.

+0

정렬로 무엇을 의미합니까? – Lauer

+0

모든 객체를 임의의 주소에 배치 할 수있는 것은 아니며 일부는 배치 할 수있는 주소에 대한 특정 제한 사항을 가지고 있습니다 (예 : 일부 플랫폼에서는 32 비트 정수가 정확히 4 바이트의 배수에 머무를 수 있음). 이런 종류의 문제를 해결하기 위해 필자는 필요할 때보 다 더 큰 "backing storage"sizeof (t)를 가지게 될 것이고, 그리고 나서'alignof' 연산자 /'align' 함수를 사용하여 저장소로 실제 사용할 첫 번째 주소를 결정할 것입니다. 유형 't'의 객체. –

+0

... 실제로, 당신은 또 다른 속임수를 사용할 수 있습니다 : "backing storage"는 자동으로 생성/파괴되지 않는 유형의 단일 요소 인'union '안에있을 수 있습니다 (C++ 11, [class .union] ¶2-4)하지만, 전체적으로 t 타입에 맞게 올바르게 정렬되어 있음을 보장한다. –