我已经阅读了https://medium.com/@vgasparyan1995/what-is-an-allocator-c8df15a93ed,他向他解释了分配器的工作原理,但是当我实现以下代码时,它总是给我0个结果。代码和MSVC有什么问题?
Allocator.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);
}
};
}
Main.cpp
#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>;
是的,你很近。成员allocate
和deallocate
是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);
}