2012-01-26 40 views
0

我想知道如何创建类似于std::map<T1, T2>(T1allocator, T2allocator, T1deallocator, T2deallocator)的东西,以便当任何人试图从任何堆中将密钥< - >值对插入到我的地图中或修改某些数据时,将在原始地图创建者堆中创建堆而不在其他堆中试图通过它来获取自己的数据?假设我们有一个DLL库(在Windows上),我们在运行时将它附加到我们的主应用程序。该库(作为主要应用程序)是用静态运行时编译的。所以可能会得到2个不同的STL和deffenetly 2个不同的堆 - 一个与应用程序的DLL。std :: map分配器绑定到所有键和值的堆?

现在说我们希望我们的插件/ dll只能使用我们的主应用程序堆中的内存。

让我们来看一些简单的演示代码。

我们创建了被称为我们的主要应用一个简单的插件接口:

class plugin: 
{ 
public: 
    virtual void pass_and_modify_data(boost::shared_ptr<std::map<std::string, std::string> > a) =0; 
}; 

我们创造了普金DLL有:

#include "plug_in_interface.h" 
class my_plugin: public plugin 
{ 
    public: 
     virtual void pass_and_modify_data(boost::shared_ptr<std::map<std::string, std::string> > a) 
     { 
      a->insert(std::pair<std::string, std::string>("hello", "World")); 
      (*a)["world"] = "hello"; 
     } 
}; 

现在,我们希望从我们应用插件通过地图,使所有传递给我们的地图的应用都分配在主应用堆上。

如何做到这样的事情 - 如何使std::map重新分配给主键的应用程序哈希与插件代码开发人员注意到? (这里由注意到我的意思是这样的东西投入的地图字符串与custome deallocators或书面方式任何特殊的非平凡代码)


看着sehe's答案,并演示中,我想创建:

如果我把它写我的主要会是什么样子:

#include <iostream> 
#include <string> 
#include <boost/shared_ptr.hpp> 
#include <boost/flyweight.hpp> 
#include "plug_in_interface.h" 

using namespace boost; 
using namespace boost::flyweights; 
typedef flyweight< 
    std::string, 
    hashed_factory< 
    boost::hash<std::string>, 
    std::equal_to<key_value>, 
    std::allocator<boost::mpl::_1> // here we get errors like C2065: 'key_value' : undeclared identifier  
    > 
> customString; 

int main() 
{ 
// boring part - load plugin... into something like boost::shared_ptr<plugin> my_plugin 
//intresting part - create map in main heap and make all its values and keys be forced to be allocated or reallocated in main heap 

    std::cout << std::endl << "Map allocator mased memory management:" << std::endl; 
    std::cin.get(); 
    { 
     boost::shared_ptr<std::map<std::string, std::string> > a (new std::map<customString, customString>()); 
     my_plugin->pass_and_modify_data(a); 
     std::cout << "modified data: " << (*a)["hello"] << (*a)["world"] << std::endl; 
    } 
    std::cout << "removed data" << std::endl; 
    std::cin.get(); 

    } 

目前我不能编译,因为customString类型的定义方式这个东西..编译器显示万吨编译器错误的。如何使类型更正确?

Jenerally我是绝对罚款与STL ::只有我真正需要的分配器件事是分配器是一些如何绑定到堆(我们都可以用做shared_ptrs),就是这样的事情可能吗?

+0

你有没有考虑只是_不做那个_? (不要将共享库静态链接到运行时...)。另外,如果您在主程序中构建地图并传递它,则会将分配器一起复制。 – sehe

+0

@sehe:为什么我需要这样一个愚蠢的事情,即静态地将一个共享库链接到它的运行时 - 使最终用户无需安装任何运行时=)另外我的主应用程序是静态编译的,插件的目的是什么是否被编译? – myWallJSON

+0

这是一个逆转。动态加载的要点是什么,如果你想动态链接的东西?另外,你为什么问这个问题?你有你的理由。想想这个,你可能**最好**不用动态链接,而是用纯C插件接口(使用HANDLE idioms)**或**使用COM接口来解决这个问题,这正是Windows上的这种用途 – sehe

回答

1

如果你只是想提供函数map做分配,你运气不好。控制STL容器内存管理的标准方法是通过allocators

由于std::map只接受一个分配器模板参数(std::map<Key, Value, Predicate, Allocator>),所以不能对键和值使用单独的分配器。但是没有理由这样做 - 一个单独的分配器就足够了。

如果你只是想要一个自定义的分配器,这很简单。您可以使用其中一种标准版本(alloc,pthread_alloc,single_client_allocmalloc_alloc),或者阅读this tutorial以了解如何编写自己的。如果您可以提供更多关于您尝试解决的问题的信息,我可能会提供更有帮助的答案。

+0

更新问题与演示细节。 – myWallJSON

1

您可以使用Boost Flywheight或Boost可选。

虽然不完全像标准容器,但它们允许工厂/分配策略,您可以使用它。当然,你最终会得到另一层间接的,可能会或可能不会成为你想要的。

参见,例如, http://www.boost.org/doc/libs/1_48_0/libs/flyweight/doc/tutorial/configuration.html#factories

hashed_factory<[Hash[,Pred[,Allocator]]]> ....

假设我们想为为std :: string轻量级用特殊的哈希谓词special_hash和自定义分配器custom_allocator配置hashed_factory;

typedef flyweight< 
    std::string, 
    hashed_factory< 
    special_hash<std::string>, 
    std::equal_to<key_value>, 
    custom_allocator<boost::mpl::_1> 
    > 
> customString; 

由于飞铁本身不变,他们将更好地为键:

std::map<customString, int> my_funky_map; 

现在,使用默认的地图分配给指定的,这将被规定如下地图的元素(对)应该被分配。


+0

添加了一些我实际尝试测试的细节。试过你的建议,得到了大量的编译器错误。你可以请示范我的例子如何使用flyweight? – myWallJSON

+0

@myWallJSON:呃...你真的尝试过吗?这里你去:http://ideone.com/0ncl1 - 请注意,如果键和值都使用相同的分配器,你最好使用'std :: map'的分配器模板参数(分配一个std: :一对字符串),这非常简单。然后再次,这个问题是_explicitely_ **没有关于那个... – sehe

+0

嗯)提供的代码编译,我的应用程序也可以修改它...但遗憾的是它不会使分配到主堆中的值分配到lib/app对。 – myWallJSON