2013-03-19 128 views
16

在C++中,你可以這樣做:編譯時數據數組結構以外的數據結構?

static const char * [4] = { 
    "One fish", 
    "Two fish", 
    "Red fish", 
    "Blue fish" 
}; 

...這給你一個很好的只讀數組的數據結構,不採取任何CPU週期在運行時進行初始化,因爲所有的數據已由編譯器爲您編寫(在可執行文件的只讀內存頁中)。

但如果我寧願使用不同的數據結構,而不是一個數組?例如,如果我想我的數據結構,必須通過一鍵快速查找,我不得不做這樣的事情:

static std::map<int, const char *> map; 

int main(int, char **) 
{ 
    map.insert(555, "One fish"); 
    map.insert(666, "Two fish"); 
    map.insert(451, "Red fish"); 
    map.insert(626, "Blue fish"); 

    [... rest of program here...] 
} 

...這是那麼優雅和效率較低的地圖數據結構即使在編譯時已知所有必要的數據,因此該工作在理論上可能已經完成了。

我的問題是,是否有在任何C方式++(或C++ 11),以創建一個只讀數據結構(例如地圖)其數據被完全設置在編譯時間,並因此預填充的和準備在運行時使用數組的方式?

回答

4

不容易,沒有。如果你試圖用malloc來做你的第一個例子,顯然它在編譯時不起作用。由於每一個標準集裝箱利用new(當然,std::allocator<T>::allocate(),但我們會假裝這是new現在),我們不能在編譯時做到這一點。

話雖如此,這取決於你是多麼的痛苦願意去通過,多少​​要推回編譯時間。您當然不能僅使用標準庫功能來完成此操作。在另一方面使用boost::mpl ...

#include <iostream> 

#include "boost/mpl/map.hpp" 
#include "boost/mpl/for_each.hpp" 
#include "boost/mpl/string.hpp" 
#include "boost/mpl/front.hpp" 
#include "boost/mpl/has_key.hpp" 

using namespace boost::mpl; 

int main() 
{ 
    typedef string<'One ', 'fish'> strone; 
    typedef string<'Two ', 'fish'> strtwo; 
    typedef string<'Red ', 'fish'> strthree; 
    typedef string<'Blue', 'fish'> strfour; 

    typedef map<pair<int_<555>, strone>, 
     pair<int_<666>, strtwo>, 
     pair<int_<451>, strthree>, 
     pair<int_<626>, strfour>> m; 

    std::cout << c_str<second<front<m>::type>::type>::value << "\n"; 
    std::cout << has_key<m, int_<666>>::type::value << "\n"; 
    std::cout << has_key<m, int_<111>>::type::value << "\n"; 
} 
+0

你介意回答我的問題類似,但矢量?我的價值是雙重型 http://stackoverflow.com/questions/15471122/getting-started-with-boost-mpl-with-vector-and-push-back – woosah 2013-03-19 11:55:39

8

如果你想有一個地圖(或設置),而不是考慮使用binary tree stored as an array。可以斷言,它在運行時在調試版本正常有序的,但在優化構建,你可以只承擔一切合理安排,然後可以做同樣類型的二進制搜索操作的,你會在的std ::地圖,但與底層存儲是一個數組。只需編寫一個小程序在您粘貼到您的程序之前爲您填充數據。

+2

堆排序不足以執行二分搜索。你需要一個真正的二叉搜索樹(或道德等價物)來做到這一點。 – rici 2013-03-19 02:34:25

+0

哦,當然你是對的。我會更新我的答案(這將保持與以前相似,而不是堆)。 – 2013-03-19 02:51:35

0

是,C++ 11允許支架初始化:

std::map<int, const char *> map = { 
    { 555, "One fish" }, 
    { 666, "Two fish" }, 
    // etc 
}; 
+9

是的,但是它會在運行時建立數據結構,這是OP想要避免的。 – 2013-03-19 02:28:30

+1

@JohnZwinck啊我的不好,我明白OP只是想要一個兼容靜態初始化的語法。重讀他的問題,但他的要求顯而易見。對我感到羞恥。 – syam 2013-03-19 02:31:04

+0

順便說一句,你能初始化列表構造這是一個const std :: map嗎? – Inverse 2013-03-19 17:33:48

2

值得一提的,是你的問題,從您使用地圖的事實造成的。 地圖經常被濫用。 映射的替代解決方案是一個排序的向量/數組。用於存儲長度未知的數據時,地圖只會比地圖「更好」,或者在數據頻繁更改時(並且僅在有時)存儲數據。

函數std :: sort,std :: lower_bound/std :: upper_bound是你需要的。 如果你自己,你只需要一個功能,LOWER_BOUND,對數據進行排序和數據可以是常量。

+0

「地圖只比地圖變得」更好「?你的意思是「比媒介更好」? – 2013-03-19 11:30:55

+0

map僅僅是一個例子......你可以用任何(非數組)數據結構來替代,問題將會是相同的。 – 2013-03-19 15:12:21

+0

@JeremyFriesner:是的,我知道這是一個例子。我的意思是說「地圖變得比地圖更好」聽起來像是一個錯字。 – 2013-03-19 17:55:42