我试图为std::vector<char>
使用自定义分配器,但我注意到std::vector
不需要/使用我的分配器中的任何成员函数。这怎么可能?
#include <vector>
struct A : private std::allocator<char> {
typedef std::allocator<char> alloc;
using alloc::value_type;
using alloc::pointer;
using alloc::const_pointer;
using alloc::difference_type;
using alloc::size_type;
using alloc::rebind;
// member functions have been removed, since the program compiles without them
};
int main() {
std::vector<char, A> v;
v.resize(4000);
for (auto& c : v)
if (c)
return 1; // never happens in my environment
return 0; // all elements initialized to 0. How is this possible?
}
我使用在线C ++ 11编译器(LiveWorkSpace)尝试上述程序,提供g ++ 4.7.2,4.8和4.6.3。
基本上allocate()
,deallocate()
,construct()
和destroy()
未在我的分配器中定义,但程序编译并且所有元素都将初始化为0。
答案 0 :(得分:14)
GCC标准库将始终重新绑定提供的分配器,因此在内部它会执行类似这样的操作(在C ++ 03中):
typedef Alloc::template rebind<value_type>::other _Allocator_type;
(在C ++ 11中它使用allocator_traits
但在这种情况下结果是相同的。)
然后,向量在内部存储该类型的对象,并将其用于所有(de)分配。
由于您尚未在分配器中定义rebind
成员模板,因此您刚刚从基类重新声明了该模板,重新绑定的结果为std::allocator<value_type>
而不是您自己的类型。 std::allocator
当然提供了所有这些功能,因此无论您是否使用自己的类型定义它们,都会使用这些功能。
您可以通过将其添加到using alloc::rebind;
的分配器整数来修复它,以便vector
在内部存储和使用A
:
struct A : private std::allocator<char> {
template<typename U>
struct rebind {
typedef A other;
};
N.B。这只适用于vector
,因为vector
并不严格需要重新绑定分配器(用户需要使用allocator<value_type>
实例化模板,但GCC的vector
仍然重新绑定因此,如果用户实例化vector<int, std::allocator<char>>
它仍然有效。)对于基于节点的容器,例如std::set
,您的分配器必须是可以反弹的模板,因为容器需要分配其内部节点类型,而不是value_type
,因此需要Alloc::rebind<internal_node_type>::other
才有效。
答案 1 :(得分:7)
vector
将重新绑定分配器。当您将其带入std::allocator
的范围时,A::rebind<T>::other
将只是std::allocator<T>
。所以一切正常。