自定义 std::allocator_traits::construct

Customizing std::allocator_traits::construct

我想自定义 std::vector 行为以不默认构造元素类型(例如 int),因为对大型向量执行此操作的成本很高。

看着这个,我能看到的唯一方法就是专业化 std::allocator_traits<MyAllocator>::construct。然而,这似乎是不可能的,因为特化必须在与原始声明相同的命名空间中。

namespace std 中设置专业似乎已经不对了。实际上比这更糟糕,因为我使用的 STL 实现实际上将 std::allocator_traits 放在 namespace std::__u 中(并且在 STL 实现中肯定会有所不同),所以这样做似乎是非常错误的。

这很令人困惑,因为似乎 std::allocator_traits 旨在允许专业化,但我不知道如何真正做到这一点。这只是一个坏主意吗?如果是这样,是否有其他方法可以解决问题(避免在 STL 容器中默认构造元素)?

专门化标准库特征 类 不仅是允许的,而且是提供此类功能的主要方式。但是,在这种特殊情况下,这是不必要的。

默认的 std::allocator_traits<T>::construct 实现(其中 T 是您的分配器类型,而不是与其一起使用的容器的值类型)将调用 construct 的成员函数T if T 有这样的函数,如果T 没有合适的成员,它调用placement-new。所以简单地给你的分配器一个 construct 成员,你应该没问题。

您应该调用 reserve 而不是 resize。只有当值已知时才添加元素。创建一个充满垃圾的 vector 是没有意义的。

std::vector<int> v;
r.reserve(500);
v.push_back(3); // Only 1 constructor is called

如果你真的不想初始化数据但仍然填充它,那么使用 struct 和不初始化其成员的构造函数应该做;

struct unintialized_int
{
    unintialized_int() { /* no initialization */ }
    int uninitialized;
};

std::vector<unintialized_int> v;
v.resize(500);
v[22].uninitialized = 33;

However, I would not recommend that as it can lead to hard to find bugs!
Better to use vector as intended.

顺便说一下,要对像 int 这样的琐碎类型的性能产生影响,您必须拥有数千个项目或创建数千个向量。

问自己一些问题:

  • 您是否在衡量发布版本的性能?调试构建可能会显着变慢。
  • 您是否分析了您的应用程序以确定是构造函数导致了速度下降?事实上,对于像 int 这样的普通类型,编译器可能能够将初始化优化为 memset.
  • 您确定初始化对性能有任何可衡量的影响吗?