自定义 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
.
- 您确定初始化对性能有任何可衡量的影响吗?
我想自定义 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
. - 您确定初始化对性能有任何可衡量的影响吗?