簡體   English   中英

如何將自定義分配器的完全相同的狀態傳遞給多個容器?

[英]How can I pass the exact same state of an custom allocator to multiple containers?

我正在編寫一個分配器,它引用了某個類的另一個實例來跟蹤分配的字節數。

下面是我正在嘗試做的一個最小的例子(從這里改編),只是沒有整個內存跟蹤類,而是我引用了一些int來收集到目前為止分配的字節。 此引用在main中分配,應傳遞給CustomAllocator:

#include <limits>   // numeric_limits
#include <iostream>
#include <typeinfo> // typeid

// container
#include <vector>
#include <list>
#include <forward_list>

template<typename T>
class CustomAllocator {
public:
    // type definitions
    typedef T value_type; /** Element type */
    typedef T* pointer; /** Pointer to element */
    typedef T& reference; /** Reference to element */
    typedef const T* const_pointer; /** Pointer to constant element */
    typedef const T& const_reference; /** Reference to constant element */
    typedef std::size_t size_type; /** Quantities of elements */
    typedef std::ptrdiff_t difference_type; /** Difference between two pointers */

    template<typename U>
    struct rebind {
        typedef CustomAllocator<U> other;
    };

    // return maximum number of elements that can be allocated
    size_type max_size () const throw() {
        return std::numeric_limits<std::size_t>::max() / sizeof(T);
    }

    CustomAllocator(std::size_t& memAllocated) :
            m_totalMemAllocated(memAllocated) {
        std::cout << "construct " << typeid(T).name() << std::endl;
    }

    CustomAllocator(const CustomAllocator& src) :
            m_totalMemAllocated(src.m_totalMemAllocated) {
        std::cout << "copy construct " << typeid(T).name() << std::endl;
    }

    template<class U>
    CustomAllocator(const CustomAllocator<U>& src) :
            m_totalMemAllocated(src.getTotalMemAllocated()) {
    }

    // allocate but don't initialize num elements of type T
    pointer allocate(size_type num, const void* = 0) {
        m_totalMemAllocated += num * sizeof(T);
        // print message and allocate memory with global new
        std::cout << "allocate " << num << " element(s)" << " of size "
                << sizeof(T) << std::endl;
        pointer ret = (pointer) (::operator new(num * sizeof(T)));
        std::cout << " allocated at: " << (void*) ret << std::endl;
        return ret;
    }

    // deallocate storage p of deleted elements
    void deallocate(pointer p, size_type num) {
        m_totalMemAllocated -= num * sizeof(T);
        // print message and deallocate memory with global delete
        std::cout << "deallocate " << num << " element(s)" << " of size "
                << sizeof(T) << " at: " << (void*) p << std::endl;
        ::operator delete((void*) p);
    }




    // initialize elements of allocated storage p with value value
    // no need to call rebind with this variadic template anymore in C++11
    template<typename _U, typename ... _Args>
    void construct(_U* p, _Args&&... args) {
        ::new ((void *) p) _U(std::forward<_Args>(args)...);
    }

    // destroy elements of initialized storage p
    template<typename _U>
    void destroy(_U* p) {
        p->~_U();
    }

    // return address of values
    pointer address (reference value) const {
        return &value;
    }
    const_pointer address (const_reference value) const {
        return &value;
    }

private:
    std::size_t& m_totalMemAllocated;
};

template<typename T, typename U>
bool operator==(const CustomAllocator<T> a, const CustomAllocator<U>& b) {
    return true;
}

template<typename T, typename U>
bool operator!=(const CustomAllocator<T>& a, const CustomAllocator<U>& b) {
    return false;
}

int main() {

    std::size_t memAllocated = 0;

    CustomAllocator<int> allocatorInstance(memAllocated);

    std::vector<int> foo(allocatorInstance);
    foo.push_back(23);
    foo.push_back(12);
    foo.push_back(8);

    std::cout << "---" << std::endl;

    // here the same
    std::list<double> bar(allocatorInstance);
    bar.push_back(3.44);
    bar.push_back(1.18);
    bar.push_back(2.25);

    std::cout << "---" << std::endl;

    // debug output
    for (auto x : foo)
        std::cout << x << " ";
    for (auto x : bar)
        std::cout << x << " ";

    std::cout << "\nalloc_count: " << memAllocated << std::endl;

    std::cout << '\n';
    return 0;
}

我的問題在於我不知道如何將分配器實例的完全相同的狀態(在示例m_totalMemAllocated中)傳遞給其他兩個容器(這里:foo和bar)。 由於標准規定C ++ 11分配器可以具有狀態。

更新:

謝謝你到目前為止的答案:)

我知道您通常將CustomAllocators作為模板參數傳遞給std容器; 像這樣:

std::vector<int, CustomAllocator<int> > foo;
std::list<double, CustomAllocator<double> > bar;

另請參見: 作為模板參數提供的allocator與作為C ++容器中的構造函數參數提供的allocator之間的區別?

但在這里我確實有一個我無法傳遞的狀態,默認構造函數將被調用,除非我給引用一些默認值(但這不是我想要的),我不能使用它。

投入

std::size_t memAllocated = 0;

從main到全局范圍將意味着使用CustomAllocator的所有容器最終將使用全局定義的memAllocated。 但我想擴展它,以便我可以有一些額外的內存或實例memAllocated2然后再次分配給其他一些分配器實例。

邊注:

有關與STD-Containers不同的容器的有狀態版本的分配器,請參閱

如何使用EASTL跟蹤內存使用情況?

為了確保在所有分配器實例之間共享狀態,第一個想法是使其成為靜態成員。 但僅憑這一點是不夠的,因為不同的模板實例確實是不同的類型,並且每個都有自己的靜態成員副本。 所以我只能想象兩種方法:使狀態成為僅包含靜態成員的輔助類,或者使用單例模式:

輔助類的靜態成員:

struct CustomAllocatorState {
    static std::size_t& m_totalMemAllocated;
}
std::size_t& CustomAllocatorState::m_totalMemAllocated = 0; # do not forget definition...

template<typename T>
class CustomAllocator {
public:
    ...
    pointer allocate(size_type num, const void* = 0) {
        CustomAllocatorState::m_totalMemAllocated += num * sizeof(T);
        ...

單例模式(你可以使用任何其他C ++單例模式,這個模型很簡單,但不能抵抗靜態初始化的慘敗):

class CustomAllocatorState {
    CustomAllocatorState(): m_val(0) {}
    static CustomAllocatorState state;

public:
    int m_val;
    static CustomAllocatorState& getState() {
        return state;
    }
};
CustomAllocatorState CustomAllocatorState::state;

template<typename T>
class CustomAllocator {
public:
    ...
    CustomAllocator() :
        state(CustomAllocatorState::getState()) {
            std::cout << "construct " << typeid(T).name() << std::endl;
    }
    ...
    pointer allocate(size_type num, const void* = 0) {
        state.m_totalMemAllocated += num * sizeof(T);
        ...
private:
    CustomAllocatorState& state;
};

輔助類中的靜態成員可能更簡單,但如果您已在應用程序中使用單例模式,那么在此處使用它也是有意義的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM