17

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

4 に答える 4

8

マップ(またはセット)が必要な場合は、代わりに配列として格納されているバイナリツリーを使用することを検討してください。デバッグビルドでは実行時に適切に順序付けられていると断言できますが、最適化されたビルドでは、すべてが適切に配置されていると想定でき、std :: mapで行うのと同じ種類のバイナリ検索操作を実行できますが、基になるストレージは配列です。プログラムに貼り付ける前に、データをヒープ化するための小さなプログラムを作成するだけです。

于 2013-03-19T02:26:53.557 に答える
5

簡単ではありません。を使用して最初の例を実行しようとすると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";
}
于 2013-03-19T04:16:13.147 に答える
2

あなたの問題はあなたが地図を使っているという事実から生じているということは言及する価値があります。マップはよく使われすぎています。マップの代替ソリューションは、ソートされたベクトル/配列です。マップは、長さが不明なデータを格納するために使用される場合、またはデータが頻繁に変更される場合にのみ(場合によっては)、マップよりも「優れた」ものになります。

関数std::sort、std :: lower_bound / std::upper_boundが必要です。自分でデータを並べ替えることができる場合は、lower_boundという1つの関数のみが必要であり、データはconstにすることができます。

于 2013-03-19T10:01:26.193 に答える
0

はい、C++11ではブレース初期化子を使用できます。

std::map<int, const char *> map = {
  { 555, "One fish" },
  { 666, "Two fish" },
  // etc
};
于 2013-03-19T02:27:50.913 に答える