如何在C++中初始化私有静态const映射?

Mel*_*oun 97 c++ static initialization const map

我只需要字典或关联数组string=> int.

这种情况有类型映射C++.

但我只需要一个map forall实例( - > static),这个地图不能改变( - > const);

我用boost库找到了这种方式

 std::map<int, char> example = 
      boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');
Run Code Online (Sandbox Code Playgroud)

没有这个lib还有其他解决方案吗?我尝试过类似的东西,但是地图初始化总是存在一些问题.

class myClass{
private:
    static map<int,int> create_map()
        {
          map<int,int> m;
          m[1] = 2;
          m[3] = 4;
          m[5] = 6;
          return m;
        }
    static map<int,int> myMap =  create_map();

};
Run Code Online (Sandbox Code Playgroud)

小智 102

#include <map>
using namespace std;

struct A{
    static map<int,int> create_map()
        {
          map<int,int> m;
          m[1] = 2;
          m[3] = 4;
          m[5] = 6;
          return m;
        }
    static const map<int,int> myMap;

};

const map<int,int> A:: myMap =  A::create_map();

int main() {
}
Run Code Online (Sandbox Code Playgroud)

  • +1,谢谢.注意:我必须将初始化行放在我的实现文件中; 将它留在头文件中由于多个定义而给出了错误(初始化代码会在每次包含头时运行). (5认同)
  • 实际上,map的operator []无法在const映射上运行,因为如果不存在,该运算符会创建引用的条目(因为它返回对映射值的引用).C++ 11引入了at(KeyValT键)方法,该方法允许您使用给定键访问该项,如果它不存在则抛出异常.(http://en.cppreference.com/w/cpp/container/map/at)此方法适用于const实例,但不能用于在非const实例上插入元素([]运算符也是如此) . (4认同)
  • 为简单起见+1,当然使用`Boost.Assign`之类的设计也非常整洁:) (3认同)
  • 错误是:`const_map.cpp:22:23:错误:将'const std :: map <int,int>'作为'this'参数传递给'std :: map <_Key,_Tp,_Compare,_Alloc> :: mapped_type& std :: map <_Key,_Tp,_Compare,_Alloc> :: operator [](const key_type&)[with _Key = int; _Tp = int; _Compare = std :: less <int>; _Alloc = std :: allocator <std :: pair <const int,int >>>; std :: map <_Key,_Tp,_Compare,_Alloc> :: mapped_type = int; std :: map <_Key,_Tp,_Compare,_Alloc> :: key_type = int]'丢弃限定符[-fpermissive]` (2认同)

Dav*_*hop 93

C++ 11标准引入了统一初始化,如果您的编译器支持它,这将使这更加简单:

//myClass.hpp
class myClass {
  private:
    static map<int,int> myMap;
};
Run Code Online (Sandbox Code Playgroud)


//myClass.cpp
map<int,int> myClass::myMap = {
   {1, 2},
   {3, 4},
   {5, 6}
};
Run Code Online (Sandbox Code Playgroud)

另请参阅Professional C++中有关unordered_maps的此部分.

  • 唯一的问题是它不是“const”。您可以在类中将其定义为“static const”,在“cpp”中将其定义为“const map&lt;...&gt;”,但要访问它,您需要使用“at()”而不是“[ ]”。 (2认同)

use*_*030 12

我做的!:)

没有C++ 11就可以正常工作

class MyClass {
    typedef std::map<std::string, int> MyMap;

    struct T {
        const char* Name;
        int Num;

        operator MyMap::value_type() const {
            return std::pair<std::string, int>(Name, Num);
        }
    };

    static const T MapPairs[];
    static const MyMap TheMap;
};

const MyClass::T MyClass::MapPairs[] = {
    { "Jan", 1 }, { "Feb", 2 }, { "Mar", 3 }
};

const MyClass::MyMap MyClass::TheMap(MapPairs, MapPairs + 3);
Run Code Online (Sandbox Code Playgroud)


小智 11

如果你觉得boost::assign::map_list_of有用,但由于某些原因不能使用它,你可以写自己的:

template<class K, class V>
struct map_list_of_type {
  typedef std::map<K, V> Map;
  Map data;
  map_list_of_type(K k, V v) { data[k] = v; }
  map_list_of_type& operator()(K k, V v) { data[k] = v; return *this; }
  operator Map const&() const { return data; }
};
template<class K, class V>
map_list_of_type<K, V> my_map_list_of(K k, V v) {
  return map_list_of_type<K, V>(k, v);
}

int main() {
  std::map<int, char> example = 
    my_map_list_of(1, 'a') (2, 'b') (3, 'c');
  cout << example << '\n';
}
Run Code Online (Sandbox Code Playgroud)

知道这些东西是如何工作的很有用,特别是当它们如此短暂时,但在这种情况下我会使用一个函数:

a.hpp

struct A {
  static map<int, int> const m;
};
Run Code Online (Sandbox Code Playgroud)

a.cpp

namespace {
map<int,int> create_map() {
  map<int, int> m;
  m[1] = 2; // etc.
  return m;
}
}

map<int, int> const A::m = create_map();
Run Code Online (Sandbox Code Playgroud)


ypn*_*nos 6

解决该问题的另一种方法:

struct A {
    static const map<int, string> * singleton_map() {
        static map<int, string>* m = NULL;
        if (!m) {
            m = new map<int, string>;
            m[42] = "42"
            // ... other initializations
        }
        return m;
    }

    // rest of the class
}
Run Code Online (Sandbox Code Playgroud)

这是更有效的,因为从堆栈到堆之间没有一种类型的副本(包括所有元素上的构造函数,析构函数)。这是否重要取决于您的用例。字符串无关紧要!(但您可能会或可能不会找到此版本的“清洁器”)

  • RVO消除了我的复制和尼尔的回答。 (3认同)

Mat*_*ler 6

如果地图仅包含在编译时已知的条目,并且地图的键是整数,则根本不需要使用地图.

char get_value(int key)
{
    switch (key)
    {
        case 1:
            return 'a';
        case 2:
            return 'b';
        case 3:
            return 'c';
        default:
            // Do whatever is appropriate when the key is not valid
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Johnsyweb.我假设原始海报提供的映射仅作为示例呈现,并不表示他具有的实际映射.因此,我还假设`return key +'a' - 1`对他的实际映射不起作用. (11认同)
  • +1指出不需要地图,但是,你不能迭代这个 (5认同)
  • 但是,那个"开关"很糟糕.为什么不'返回键+'a' - 1`? (4认同)