我有一个分配器适配器,我称之为ctor_allocator
. 我写它更多是为了实验而不是为了任何实际需要。它使分配器在可行时使用默认构造,从而通过分配绕过任何默认初始化。例如,双精度向量的构造不会将值初始化为 0.0(或任何值)。
适配器中的许多代码都是旧式的,而且看起来可能很快就会被弃用,如果还没有的话。在不违背其目的的情况下,我还没有成功地对代码进行现代化改造。例如,如果我删除struct rebind
模板,则零初始化返回。
你能展示如何对其进行现代化改造吗?
答案可能对其他应用程序具有指导意义。
编辑:在评论中,布兰登将这两个链接作为“新方式”的示例。SO问题和最小示例。两者都不能防止使用零进行初始化,这发生在construct
. 但是,如果我通过添加void construct(U* ptr)
模板来修改任一示例,则可以避免零初始化。这回答了一个与我在这里提出的不同的问题,但它是一个好问题的好答案。
#include <memory>
namespace dj {
template <typename T, typename A = std::allocator<T>>
class ctor_allocator : public A
{
using a_t = std::allocator_traits<A>;
public:
using A::A; // Inherit constructors from A
template <typename U>
struct rebind {
using other = ctor_allocator<U, typename a_t::template rebind_alloc<U>>;
};
template <typename U>
void construct(U* ptr)
noexcept(std::is_nothrow_default_constructible<U>::value)
{
::new(static_cast<void*>(ptr)) U;
}
template <typename U, typename...Args>
void construct(U* ptr, Args&&... args) {
a_t::construct(static_cast<A&>(*this),
ptr, std::forward<Args>(args)...);
}
};
}
// Test case. main.cpp
#include <iostream>
#include <vector>
template<class T>
using vector = std::vector<T, dj::ctor_allocator<T>>;
int main() {
{
vector<int> v(10);
for (int i = 0; i < 10; ++i) {
v[i] = i * 56313;
}
}
// If ctor_allocator works as intended,
// this probably will not print all zeros.
vector<int> v(10);
for (int i = 0; i < 20; ++i) {
std::cout << std::hex << v[i] << " ";
}
std::cout << std::endl;
}