首页 > 解决方案 > 分配器如何在 MSVC 中工作?

问题描述

我已阅读https://medium.com/@vgasparyan1995/what-is-an-allocator-c8df15a93ed,他解释了分配器的工作原理,但是当我实现以下代码时,它总是给我 0 结果。代码和 MSVC 有什么问题?

分配器.h

#pragma once

#include <atomic>
#include <memory>
#include <iostream>
#include <vector>
#include <list>
#include <set>


namespace Milad
{
    std::atomic_int GMemoryUsed(0);

    template <typename T>
    class Allocator : public std::allocator<T>
    {
    private:
        using PrBase = std::allocator<T>;
        using PrPointer = typename std::allocator_traits<PrBase>::pointer;
        using PrSizeType = typename std::allocator_traits<PrBase>::size_type;
    public:
        Allocator() = default;

        template <typename U>
        Allocator(const Allocator<U>& arg_other) : PrBase(arg_other)
        {

        }

        template <typename U>
        struct rebind
        {
            using other = Allocator<U>;
        };

        PrPointer Allocate(PrSizeType arg_n)
        {
            GMemoryUsed.fetch_add(arg_n * sizeof(T));
            return PrBase::allocate(arg_n);
        }

        void Deallocate(PrPointer arg_p, PrSizeType arg_sz)
        {
            GMemoryUsed.fetch_sub(arg_sz * sizeof(T));
            PrBase::deallocate(arg_p, arg_sz);
        }
    };
}

主文件

#include "Allocator.h"

template <template <typename T, typename AllocT> typename ContainerT>
void Measurement()
{
    std::cout << __FUNCSIG__ << std::endl;
    std::cout << "Before Memory Usage: " << Milad::GMemoryUsed.load() << std::endl;
    ContainerT<int, Milad::Allocator<int>> Container;
    for (int i = 0; i < 1000; ++i)
    {
        Container.insert(std::end(Container), i);
    }
    std::cout << "After Memory Usage: " << Milad::GMemoryUsed.load() << std::endl;
}

template <typename T, typename AllocT>
using SetWithDefaultComparator = std::set<T, std::less<>, AllocT>;

int main(int argc, const char* argv[])
{
    Measurement<std::vector>();
    Measurement<std::list>();
    Measurement<SetWithDefaultComparator>();

    return 0;
}

当我运行程序时,它给了我以下结果:

void __cdecl Measurement<class std::vector>(void)
Before Memory Usage: 0
After Memory Usage: 0
void __cdecl Measurement<class std::list>(void)
Before Memory Usage: 0
After Memory Usage: 0
void __cdecl Measurement<SetWithDefaultComparator>(void)
Before Memory Usage: 0
After Memory Usage: 0

另外,我不明白我应该如何解释以下代码行。为什么这些行是这样实现的:

template <template <typename T, typename AllocT> typename ContainerT>

ContainerT<int, Milad::Allocator<int>> Container;

template <typename T, typename AllocT>
using SetWithDefaultComparator = std::set<T, std::less<>, AllocT>;

标签: c++visual-c++memory-management

解决方案


是的,你很接近。成员allocatedeallocate是成员,std::allocator容器正在寻找这些成员。因为您已经大写了成员的版本,所以调用了默认分配器,而您的内存覆盖则没有。您的代码应该是:

    PrPointer allocate(PrSizeType arg_n)
    {
        GMemoryUsed.fetch_add(arg_n * sizeof(T));
        return PrBase::allocate(arg_n);
    }

    void deallocate(PrPointer arg_p, PrSizeType arg_sz)
    {
        GMemoryUsed.fetch_sub(arg_sz * sizeof(T));
        PrBase::deallocate(arg_p, arg_sz);
    }

推荐阅读