【发布时间】:2022-11-29 20:26:44
【问题描述】:
我有这个代码 sn-p
auto start = high_resolution_clock::now();
std::vector<char> myBuffer(20e6);
std::cout << "StandardAlloc Time:" << duration_cast<milliseconds>(high_resolution_clock::now() - start).count() << std::endl;
start = high_resolution_clock::now();
std::vector<char, HeapAllocator<char>>myCustomBuffer(20e6);
std::cout << "CustomAlloc Time:" << duration_cast<milliseconds>(high_resolution_clock::now() - start).count() << " CC: " << HeapAllocator<char>::constructCount << std::endl;
输出:
StandardAlloc Time:6
CustomAlloc Time:124 CC: 20000000
有了这个分配器
template<class T>
struct HeapAllocator
{
typedef T value_type;
HeapAllocator(){};
template<class U>
constexpr HeapAllocator(const HeapAllocator<U>&) noexcept {}
[[nodiscard]] T* allocate(std::size_t n)
{
auto p = new T[n];
return p;
}
void deallocate(T* p, std::size_t n) noexcept
{
delete p;
}
template <class U>
void destroy(U* p)
{
destroyCount++;
}
template< class U, class... Args >
void construct(U* p, Args&&... args)
{
constructCount++;
}
static int destroyCount;
static int constructCount;
};
template<class T>
int HeapAllocator<T>::constructCount = 0;
因此很明显,与默认分配器相比,缓冲区的每个 char 元素都会调用构造/销毁,这导致执行时间增加了 20 倍。我怎样才能防止这种基本类型的这种行为?
【问题讨论】:
-
分配器不负责调用构造函数;那是
std::vector的工作。new T[n]确实调用了构造函数......例如std::vector<MyType, MyAllocator> v; v.reserve(100); v.emplace_back(param);应该导致对非默认构造函数的恰好 1 次构造函数调用,但是对于您的分配器实现,这将导致(至少)对默认构造函数的 100 次调用。 -
顺便说一句:您使用
delete而不是delete[]会导致未定义的行为。你不应该调用任何 delete 运算符,因为这将涉及调用析构函数,这也是std::vector...