2014-10-03 3 views
1

아래 코드는 32 바이트 정렬 메모리를 할당하는 사용자 지정 할당자를 정의합니다.32 바이트 정렬 메모리를 할당하는 할당 자

Visual Studio 2010에서 코드를 컴파일했습니다. 코드가 릴리스 모드에서 올바르게 컴파일됩니다. 디버그 모드에서 이해할 수없는 컴파일 오류가 발생합니다 (아래 참조). 코드에 어떤 문제가 있습니까? 디버그 모드에서

#include <memory> 
#include <vector> 

inline void* aligned_malloc(size_t n) 
{ 
    if(n == 0) return nullptr; 
    char* p = (char*)malloc(n + 32); 
    if(p == nullptr) return nullptr; 
    size_t offset = 32 - (size_t)p % 32; 
    p += offset; 
    *(p - 1) = (char)offset; 
    return p; 
} 

inline void aligned_free(void* p) 
{ 
    if(p == nullptr) return; 
    char offset = *((char*)p - 1); 
    free((char*)p - offset); 
} 

template<class T> 
class AlignedAllocator { 
public: 
    typedef T value_type; 
    typedef T* pointer; 
    typedef const T* const_pointer; 
    typedef T& reference; 
    typedef const T& const_reference; 
    typedef size_t size_type; 
    typedef ptrdiff_t difference_type; 

    T* address(T& x) const { return &x; } 
    const T* address(const T& x) const { return &x; } 

    size_t max_size() const { return (size_t)(-1)/sizeof(T); } 

    T* allocate(size_t n, const T* = nullptr) 
    { 
     T* p = (T*)aligned_malloc(n * sizeof(T)); 
     if(!p) throw std::bad_alloc(); 
     return p; 
    } 
    void deallocate(pointer p, size_type) { aligned_free(p); } 

    void construct(T* p, const T& x) { new(p) T(x); } 
    void destroy(T* p) { p->~T(); } 

    template<class U> struct rebind { typedef AlignedAllocator<U> other; }; 
}; 

std::vector<int, AlignedAllocator<int>> v; 

컴파일 오류 : 다른 것들 사이

c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector(441): error C2440: 'initializing' : cannot convert from 'AlignedAllocator<T>' to 'AlignedAllocator<T>' 
     with 
     [ 
      T=int 
     ] 
     and 
     [ 
      T=std::_Container_proxy 
     ] 
     No constructor could take the source type, or constructor overload resolution was ambiguous 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector(437) : while compiling class template member function 'std::_Vector_val<_Ty,_Alloc>::_Vector_val(_Alloc)' 
     with 
     [ 
      _Ty=int, 
      _Alloc=AlignedAllocator<int> 
     ] 
     c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector(481) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled 
     with 
     [ 
      _Ty=int, 
      _Alloc=AlignedAllocator<int> 
     ] 
     c:\users\rade\desktop 5\higg boson repository\tmp\tmp.cpp(52) : see reference to class template instantiation 'std::vector<_Ty,_Ax>' being compiled 
     with 
     [ 
      _Ty=int, 
      _Ax=AlignedAllocator<int> 
     ] 

답변

3

할당자는 요구 사항, 필요로 주어진 할당 유형 X, 모든 종류의 U

당신이
using Y = typename X::template rebind<U>::other; 

X 유형의 오브젝트에서 Y을 구성 할 수 있습니다. (귀하의 코드에 적용되는 짧은 것은 임의 유형 FooBar에 대해 AlignedAllocator<Bar>에서 AlignedAllocator<Foo>을 구성 할 수 있어야한다는 것입니다. 할당자는 해당 요구 사항을 충족하지 않습니다. 디버그 모드에서 MSVC 표준 라이브러리는 디버거 용으로 몇 가지 추가 내부 데이터를 유지하도록 할당자를 리 바인드하지만 릴리스 모드에서는 그렇지 않습니다. 따라서 컴파일러가 디버그 모드에서 불만을 표시하는 것입니다.

수정은 간단합니다 - 그냥 필요한 생성자를 추가

여기
AlignedAllocator() { } 
template<class U> AlignedAllocator(const AlignedAllocator<U> &) { } 
+0

고마워요. 문제가 해결되었습니다. – user763305

0

코드의 작업 버전입니다. 내 질문의 코드와 T.C의 대답을 결합합니다. 및 몇 가지 추가 수정 사항. 누군가가 유용하다고 생각할 수 있기 때문에 여기에 게시하고 있습니다.

코드는 MSVS 2008 및 MSVS 2010에서 테스트되었으며, C++ 98로 작성되었습니다. C++ 11 할당 자 요구 사항을 준수하기 위해 일부 변경이 필요할 수 있습니다.

#include <cstdlib> 
#include <new> 

inline void* alignedMalloc(size_t n) 
{ 
    char* p = (char*)std::malloc(n + 32); 
    if(!p) return 0; 
    size_t offset = 32 - (size_t)p % 32; 
    p += offset; 
    *(p - 1) = (char)offset; 
    return p; 
} 

inline void alignedFree(void* p) 
{ 
    if(!p) return; 
    char offset = *((char*)p - 1); 
    std::free((char*)p - offset); 
} 

template<class T> 
class AlignedAllocator { 
public: 
    typedef T value_type; 
    typedef T* pointer; 
    typedef const T* const_pointer; 
    typedef T& reference; 
    typedef const T& const_reference; 
    typedef size_t size_type; 
    typedef ptrdiff_t difference_type; 

    AlignedAllocator() {} 
    template<class U> AlignedAllocator(const AlignedAllocator<U>&) {} 

    T* address(T& x) const { return &x; } 
    const T* address(const T& x) const { return &x; } 

    size_t max_size() const { return (size_t)(-1)/sizeof(T); } 

    T* allocate(size_t n, const T* = 0) 
    { 
     T* p = (T*)alignedMalloc(n * sizeof(T)); 
     if(!p) throw std::bad_alloc(); 
     return p; 
    } 

    void deallocate(T* p, size_t) { alignedFree(p); } 

    void construct(T* p, const T& x) { new(p) T(x); } 
    void destroy(T* p) { (void)p; p->~T(); }   // (void)p silences spurious MSVS 2010 compiler warning 

    template<class U> struct rebind { typedef AlignedAllocator<U> other; }; 
}; 

template <class T> 
bool operator==(const AlignedAllocator<T>&, const AlignedAllocator<T>&) { return true; } 

template <class T> 
bool operator!=(const AlignedAllocator<T>&, const AlignedAllocator<T>&) { return false; }