2015-09-15 16 views
8

我玩std :: function和自定義分配器,但它不像我所期望的那樣運行,當我不提供函數初始函數時。與自定義分配器但沒有其他參數的std :: function構造函數有什麼意義?

當我向構造函數提供自定義分配器但沒有初始函數時,分配器從不使用或看起來如此。

這是我的代碼。

//Simple functor class that is big to force allocations 
struct Functor128 
{ 
    Functor128() 
    {} 

    char someBytes[128]; 

    void operator()(int something) 
    { 
     cout << "Functor128 Called with value " << something << endl; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
Allocator<char, 1> myAllocator1; 
Allocator<char, 2> myAllocator2; 
Allocator<char, 3> myAllocator3; 
Functor128 myFunctor; 

cout << "setting up function1" << endl; 
function<void(int)> myFunction1(allocator_arg, myAllocator1, myFunctor); 
myFunction1(7); 

cout << "setting up function2" << endl; 
function<void(int)> myFunction2(allocator_arg, myAllocator2); 
myFunction2 = myFunctor; 
myFunction2(9); 

cout << "setting up function3" << endl; 
function<void(int)> myFunction3(allocator_arg, myAllocator3); 
myFunction3 = myFunction1; 
myFunction3(19); 
} 

輸出:

setting up function1 
Allocator 1 allocating 136 bytes. 
Functor128 Called with value 7 

setting up function2 
Functor128 Called with value 9 

setting up function3 
Allocator 1 allocating 136 bytes. 
Functor128 Called with value 19 

所以案例1:myFunction1分配使用allocator1預期。 case2:myFunction2在構造函數中被賦予了allocator2,但是當賦給一個functor時,它似乎重置爲使用默認的std :: allocator來進行分配(因此沒有關於分配的打印輸出)。

case3:myFunction3在構造函數中給出allocator3,但是當從myFunction1分配給myFunction3時,分配將使用函數1的分配器進行分配。

這是正確的行爲? 特別是,在情況2爲什麼恢復使用默認的std :: allocator? 如果是這樣的話,分配器作爲分配器的空構造函數的用處永遠不會被使用。

我正在使用VS2013代碼。

我的分配器類只是一個使用新的和註銷時,它分配

template<typename T, int id = 1> 
class Allocator { 
public: 
    // typedefs 
    typedef T value_type; 
    typedef value_type* pointer; 
    typedef const value_type* const_pointer; 
    typedef value_type& reference; 
    typedef const value_type& const_reference; 
    typedef std::size_t size_type; 
    typedef std::ptrdiff_t difference_type; 

public: 
    // convert an allocator<T> to allocator<U> 
    template<typename U> 
    struct rebind { 
     typedef Allocator<U> other; 
    }; 

public: 
    inline Allocator() {} 
    inline ~Allocator() {} 
    inline Allocator(Allocator const&) {} 
    template<typename U> 
    inline Allocator(Allocator<U> const&) {} 

    // address 
    inline pointer address(reference r) { return &r; } 
    inline const_pointer address(const_reference r) { return &r; } 

    // memory allocation 
    inline pointer allocate(size_type cnt, 
     typename std::allocator<void>::const_pointer = 0) 
    { 
     size_t numBytes = cnt * sizeof (T); 
     std::cout << "Allocator " << id << " allocating " << numBytes << " bytes." << std::endl; 
     return reinterpret_cast<pointer>(::operator new(numBytes)); 
    } 
    inline void deallocate(pointer p, size_type) { 
     ::operator delete(p); 
    } 

    // size 
    inline size_type max_size() const { 
     return std::numeric_limits<size_type>::max()/sizeof(T); 
    } 

    // construction/destruction 
    inline void construct(pointer p, const T& t) { new(p)T(t); } 
    inline void destroy(pointer p) { p->~T(); } 

    inline bool operator==(Allocator const&) { return true; } 
    inline bool operator!=(Allocator const& a) { return !operator==(a); } 
}; // end of class Allocator 
+0

有一個建議,從'std :: function'去除分配器支持:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0302r0.html,並提供一個有用的列表已知問題 –

回答

5

std::function的分配器的支持......怪異的最小實現。

operator=(F&& f)的當前規格是std::function(std::forward<F>(f)).swap(*this);。如您所見,這意味着f的內存默認使用任何std::function,而不是用於構造*this的分配器。所以你觀察到的行爲是正確的,雖然令人驚訝。

此外,由於(allocator_arg_t, Allocator)(allocator_arg_t, Allocator, nullptr_t)構造函數是noexcept,即使他們想要(分配器的類型擦除可能需要動態分配),它們也不能真正存儲分配器。因爲它們基本上不存在以支持使用分配器構造協議。

LWG最近拒絕了an issue這將改變這種行爲。

+0

他們對使用分配器構造協議(和「std :: scoped_allocator_adaptor」)付出了口頭上的支持,但實際上並不支持它。也許這就是海灣合作委員會選擇不實施口頭承諾的原因。我正在提出一種替代解決方案:http://bit.ly/allocfun(PDF)。 – Potatoswatter

+0

是否規定保存在'std :: function'中的可調用對象應該被'std :: function'使用的分配器刪除?或者只是使用'delete p'? – linux40

+0

@ linux40分配器不能在類型擦除之後對任意類型的''構造'或'銷燬'(參見[LWG2502](http:// wg21。鏈接/ LWG2502),其中談到'構造',但同樣適用於'銷燬')。顯然必須使用分配器完成釋放;析構函數可能會直接調用。 –

相關問題