带有 STL 向量的自定义分配器(在 Visual Studio 工具链中)
Custom allocator with a STL vector (within Visual Studio toolchain)
将自定义分配器与 STL 向量(在 Visual Studio 工具链中)一起使用时,构造函数被调用 3 次,析构函数被调用 4 次。我错过了什么?以下是代码及其输出:
#include <iostream>
#include <stdlib.h>
#include <new>
#include <memory>
#include <vector>
using namespace std;
template <class T>
struct Mallocator
{
typedef T value_type;
Mallocator() noexcept { cout << "Mallocator() " << this << endl; }
~Mallocator() noexcept { cout << "~Mallocator() " << this << endl; }
template<class U> Mallocator(const Mallocator<U>&) noexcept { cout << "Mallocator(const Mallocator<U>&) " << this << endl; }
template<class U> Mallocator(Mallocator<U>&&) noexcept { cout << "Mallocator(Mallocator<U>&&) " << this << endl; }
template<class U> bool operator==(const Mallocator<U>&) const noexcept
{
return true;
}
template<class U> bool operator!=(const Mallocator<U>&) const noexcept
{
return false;
}
T* allocate(const size_t n) const;
void deallocate(T* const p, size_t) const noexcept;
};
template <class T>
T* Mallocator<T>::allocate(const size_t n) const
{
cout << " allocate from" << this << endl;
if (n == 0)
{
return nullptr;
}
if (n > static_cast<size_t>(-1) / sizeof(T))
{
throw std::bad_array_new_length();
}
void* const pv = malloc(n * sizeof(T));
if (!pv) { throw std::bad_alloc(); }
return static_cast<T*>(pv);
}
template<class T>
void Mallocator<T>::deallocate(T * const p, size_t) const noexcept
{
cout << " deallocate from" << this << endl;
free(p);
}
int main()
{
Mallocator<uint8_t> mall{};
std::vector<uint8_t, Mallocator<uint8_t>> v(mall);
return 0;
}
输出如下:
Mallocator() 0058FDF3
Mallocator(const Mallocator<U>&) 0058FADF
allocate from0058FADF
~Mallocator() 0058FADF
Mallocator(const Mallocator<U>&) 0058FAF3
deallocate from0058FAF3
~Mallocator() 0058FAF3
~Mallocator() 0058FDD8
~Mallocator() 0058FDF3
此外,即使不使用向量,分配器也已经被实例化了 3 次(或者可能是 4 次,因为析构函数被调用了 4 次),这与仅实例化它一次的 GCC 工具链相比要多得多。
我已将复制和移动构造函数添加到您在 template <class T> struct Mallocator
中的代码中
Mallocator(const Mallocator&) { cout << "Mallocator&() " << this << endl; }
Mallocator(const Mallocator&&) { cout << "Mallocator&&() " << this << endl; }
这是我使用 GCC 7.1.0 得到的输出:
Mallocator() 0x61fe3f
Mallocator&() 0x61fe20
~Mallocator() 0x61fe20
~Mallocator() 0x61fe3f
本次调用构造函数和析构函数的次数匹配。您也可以在 Visual Studio 工具链中对此进行测试。
将自定义分配器与 STL 向量(在 Visual Studio 工具链中)一起使用时,构造函数被调用 3 次,析构函数被调用 4 次。我错过了什么?以下是代码及其输出:
#include <iostream>
#include <stdlib.h>
#include <new>
#include <memory>
#include <vector>
using namespace std;
template <class T>
struct Mallocator
{
typedef T value_type;
Mallocator() noexcept { cout << "Mallocator() " << this << endl; }
~Mallocator() noexcept { cout << "~Mallocator() " << this << endl; }
template<class U> Mallocator(const Mallocator<U>&) noexcept { cout << "Mallocator(const Mallocator<U>&) " << this << endl; }
template<class U> Mallocator(Mallocator<U>&&) noexcept { cout << "Mallocator(Mallocator<U>&&) " << this << endl; }
template<class U> bool operator==(const Mallocator<U>&) const noexcept
{
return true;
}
template<class U> bool operator!=(const Mallocator<U>&) const noexcept
{
return false;
}
T* allocate(const size_t n) const;
void deallocate(T* const p, size_t) const noexcept;
};
template <class T>
T* Mallocator<T>::allocate(const size_t n) const
{
cout << " allocate from" << this << endl;
if (n == 0)
{
return nullptr;
}
if (n > static_cast<size_t>(-1) / sizeof(T))
{
throw std::bad_array_new_length();
}
void* const pv = malloc(n * sizeof(T));
if (!pv) { throw std::bad_alloc(); }
return static_cast<T*>(pv);
}
template<class T>
void Mallocator<T>::deallocate(T * const p, size_t) const noexcept
{
cout << " deallocate from" << this << endl;
free(p);
}
int main()
{
Mallocator<uint8_t> mall{};
std::vector<uint8_t, Mallocator<uint8_t>> v(mall);
return 0;
}
输出如下:
Mallocator() 0058FDF3
Mallocator(const Mallocator<U>&) 0058FADF
allocate from0058FADF
~Mallocator() 0058FADF
Mallocator(const Mallocator<U>&) 0058FAF3
deallocate from0058FAF3
~Mallocator() 0058FAF3
~Mallocator() 0058FDD8
~Mallocator() 0058FDF3
此外,即使不使用向量,分配器也已经被实例化了 3 次(或者可能是 4 次,因为析构函数被调用了 4 次),这与仅实例化它一次的 GCC 工具链相比要多得多。
我已将复制和移动构造函数添加到您在 template <class T> struct Mallocator
Mallocator(const Mallocator&) { cout << "Mallocator&() " << this << endl; }
Mallocator(const Mallocator&&) { cout << "Mallocator&&() " << this << endl; }
这是我使用 GCC 7.1.0 得到的输出:
Mallocator() 0x61fe3f
Mallocator&() 0x61fe20
~Mallocator() 0x61fe20
~Mallocator() 0x61fe3f
本次调用构造函数和析构函数的次数匹配。您也可以在 Visual Studio 工具链中对此进行测试。