参考C++ named requirements: Allocator - cppreference.com
自定义的内存分配器类要实现
T* allocate(std::size_t n)与
void deallocate(T* p, std::size_t n)
两个方法,详见:
代码part1:
#include <cstdlib>
#include <new>
#include <limits>
#include <iostream>
#include <vector>
using namespace std;
class Mtype{
public:
int value;
Mtype():value(-1){ // 默认构造函数
cout<<"calling default Mtype()"<<endl;
}
Mtype(int val):value(val){ // 自定义构造函数
cout<<"calling Mtype(int)"<<endl;
}
Mtype(const Mtype &obj):value(obj.value){ // 拷贝构造函数
cout<<"calling Mtype(const Mtype &obj)"<<endl;
}
Mtype & operator=(const Mtype &obj){ // 拷贝赋值运算符函数
value = obj.value;
cout<<"calling Mtype &operator=(const Mtype &obj)"<<endl;
return *this;
}
Mtype(Mtype &&obj):value(obj.value){ // 移动构造函数
cout<<"calling Mtype(Mtype &&obj)"<<endl;
}
Mtype & operator=(Mtype &&obj){ // 移动赋值运算符函数
value = obj.value;
cout<<"calling Mtype &operator=(Mtype &&obj)"<<endl;
return *this;
}
};
part2:
template<class T>
struct Mallocator // 自定义用于容器的内存分配器类
{
typedef T value_type;
Mallocator () = default;
template <class U>
constexpr Mallocator (const Mallocator <U>&) noexcept { // 拷贝构造
U obju;
cout<<"typeid(obju).name() "<<typeid(obju).name()<<endl;
T objt;
cout<<"typeid(objt).name() "<<typeid(objt).name()<<endl;
cout<<"calling Mallocator (const Mallocator <U>&) {}"<<endl;
}
[[nodiscard]] T* allocate(std::size_t n)
{
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
throw std::bad_array_new_length();
if (auto p = static_cast<T*>(std::malloc(n * sizeof(T))))
{
report(p, n);
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t n) noexcept
{
report(p, n, 0);
std::free(p);
}
private:
void report(T* p, std::size_t n, bool alloc = true) const
{
std::cout << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T) * n
<< " bytes at " << std::hex << std::showbase
<< reinterpret_cast<void*>(p) << std::dec << '\n';
}
};
part3:
template<class T, class U>
bool operator==(const Mallocator <T>&, const Mallocator <U>&) {
cout<<"calling operator==()"<<endl;
return true;
}
template<class T, class U>
bool operator!=(const Mallocator <T>&, const Mallocator <U>&) {
cout<<"calling operator!=()"<<endl;
return false;
}
void check_Mallocator(){
cout<<"breakpoint -1"<<endl;
Mallocator<int> obj; // 调用默认构造函数
Mallocator<size_t> obj2(obj); // 调用拷贝构造函数
cout<<"sizeof(Mtype) "<<sizeof(Mtype)<<endl; // 4,只一个虚函数表指针
std::vector<Mtype, Mallocator<Mtype> > v(2); // 首先申请8/4=2初始容量的内存,然后调用两次默认构造生成元素
v.push_back(42); /* 首先按照逻辑顺序调用一次自定义构造,然后2倍扩容申请16/4=4容量的内存,
然后对push_back()的右值调用移动构造,然后对旧容器的2个元素调用拷贝构造,然后释放旧容器的8/4=2个元素的内存,*/
cout<<"breakpoint 1"<<endl;
// 最后释放16/4=4容量的新容器的内存
}
void check_constructor(){
Mtype obj; // 默认构造
Mtype obj2(obj); // 拷贝构造,calling Mtype(const Mtype &obj)
obj2 = obj; // 拷贝赋值,calling Mtype &operator=(const Mtype &obj)
Mtype obj3(std::move(obj)); // 移动构造,calling Mtype(Mtype &&obj)
obj3 = std::move(obj2); // 移动赋值,calling Mtype &operator=(Mtype &&obj)
}
int main()
{
// check_Mallocator();
check_constructor();
}