2012-01-26 70 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