问题描述
如何覆盖STL中allocator类中构造方法的默认行为?以下似乎无效:
#include< list>
#include< iostream>
#include< memory>
struct MyObj {
MyObj(){
std :: cout< 这是构造函数< std :: endl;
}
MyObj(const MyObj& x){
std :: cout< 这是复制构造函数< std :: endl;
}
};
class MyAlloc:public std :: allocator< MyObj> {
public:
void construct(pointer p,const_reference t){
std :: cout ;& 在分配器中构造< std :: endl;
new((void *)p)MyObj(t);
}
};
int main(){
MyObj x;
std :: list< MyObj,MyAlloc> list(5,x);
}
此程序返回
这是构造函数
这是复制构造函数
这是复制构造函数
这是复制构造函数
这是副本构造函数
这是复制构造函数
我希望它返回
这是构造函数
在分配器中的构造
这是复制构造函数
在分配器中的构造
这是复制构造函数
在分配器中的构造
这是复制构造函数
在分配器中的构造
这是复制构造函数
在分配器中的构造
这是复制构造函数
奇妙的分配器世界。
规则#1:不要从 std :: allocator派生
。如果你想使用自己的分配方案,然后写自己的分配器。如果你想覆盖std :: allocator中的某些功能,那么只需创建一个 std :: allocator
实例,并在未覆盖的函数中调用它的函数。 p>
请注意,派生并不真正工作。在C ++ 03中,分配器不允许有状态,并且v表指针计数为状态。所以分配器不能有虚函数。这是为什么 std :: allocator
没有虚拟函数。
规则#2: std :: list< T>
从不分配 T
对象。记住: std :: list
是一个链表。它分配节点,其中 T
为成员。它通过一些模板魔法来实现这一点,它使用它的内部节点类型作为参数来调用你的迭代器类,并返回相同模板的新的allocator对象,但是使用不同的模板参数。
它通过你的allocator调用 rebind
的模板struct成员,它有一个成员typedef叫其他
定义新的分配器类型。在你的case, std :: list
将这样做:
MyAlloc :: rebind< _ListInternalNodeType> :: other theAllocatorIWillActuallyUse();
这仍然是基类提供的。因此, MyAlloc :: rebind< _ListInternalNodeType> :: other
的类型是 std :: allocator< _ListInternalNodeType>
。这是 std :: list
将用于实际分配内容的分配器类型。
How do you overwrite the default behavior of the construct method in the allocator class in STL? The following does not seem to work:
#include <list>
#include <iostream>
#include <memory>
struct MyObj {
MyObj() {
std::cout << "This is the constructor" << std::endl;
}
MyObj(const MyObj& x) {
std::cout << "This is the copy constructor" << std::endl;
}
};
class MyAlloc : public std::allocator <MyObj>{
public:
void construct(pointer p, const_reference t){
std::cout << "Construct in the allocator" << std::endl;
new( (void*)p ) MyObj(t);
}
};
int main(){
MyObj x;
std::list <MyObj,MyAlloc> list(5,x);
}
This program returns
This is the constructor
This is the copy constructor
This is the copy constructor
This is the copy constructor
This is the copy constructor
This is the copy constructor
I would like it to return
This is the constructor
Construct in the allocator
This is the copy constructor
Construct in the allocator
This is the copy constructor
Construct in the allocator
This is the copy constructor
Construct in the allocator
This is the copy constructor
Construct in the allocator
This is the copy constructor
Welcome to the wonderful world of allocators. I hope you enjoy your stay, though that's unlikely.
Rule #1: Do not derive from std::allocator
. If you want to use your own allocation scheme, then write your own allocator. If you want to "override" some functionality in std::allocator, then simply create a std::allocator
instance and call its functions in the un-overridden functions.
Note that deriving doesn't really work anyway. In C++03, allocators aren't allowed to have state, and a v-table pointer counts as state. So allocators can't have virtual functions. Which is why std::allocator
doesn't have virtual functions.
Rule #2: std::list<T>
never allocates T
objects. Remember: std::list
is a linked list. It allocates nodes, which have a T
as a member. It does this via some template magic, where it calls your iterator class using it's internal node type as a parameter, and that returns a new allocator object of the same template, but with a different template parameter.
It does this via a template struct member of your allocator call rebind
, which has a member typedef called other
that defines the new allocator type. In your case, std::list
will do this:
MyAlloc::rebind<_ListInternalNodeType>::other theAllocatorIWillActuallyUse();
And that is still provided by the base class. So the type of MyAlloc::rebind<_ListInternalNodeType>::other
is std::allocator<_ListInternalNodeType>
. Which is the allocator type that std::list
will use to actually allocate things.
这篇关于如何覆盖C ++ STL中allocator类中构造方法的默认行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!