如何覆盖C ++ STL中allocator类中构造方法的默认行为 [英] How to overwrite the default behavor of the construct method in the allocator class in C++ STL

查看:165
本文介绍了如何覆盖C ++ STL中allocator类中构造方法的默认行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何覆盖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类中构造方法的默认行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆