我只需要字典或关联数组
string
=> int
。
对于这种情况,有类型映射 C++。
但是我只需要一张映射来表示所有实例(-> static),并且该映射无法更改(-> const);
我用boost库找到了这种方法
std::map<int, char> example =
boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');
没有这个库还有其他解决方案吗? 我已经尝试过类似的方法,但是地图初始化总是存在一些问题。
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();
};
C++11 标准引入了统一初始化,如果您的编译器支持它,这会使事情变得更简单:
//myClass.hpp
class myClass {
private:
static const map<int,int> myMap;
};
//myClass.cpp
const map<int,int> myClass::myMap = {
{1, 2},
{3, 4},
{5, 6}
};
另请参阅 Professional C++ 中关于 unordered_maps 的本节。
#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() {
}
如果您发现
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';
}
了解这些东西是如何工作的很有用,特别是当它们很短时,但在这种情况下我会使用一个函数:
struct A {
static map<int, int> const m;
};
namespace {
map<int,int> create_map() {
map<int, int> m;
m[1] = 2; // etc.
return m;
}
}
map<int, int> const A::m = create_map();
无需 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);
如果映射仅包含编译时已知的条目并且映射的键是整数,那么您根本不需要使用映射。
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
}
}
解决问题的不同方法:
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
}
这更高效,因为没有从堆栈到堆的单一类型复制(包括所有元素的构造函数、析构函数)。这是否重要取决于您的用例。和弦没关系! (但您可能会或可能不会发现这个版本“更干净”)
你可以试试这个:
我的班级.h
class MyClass {
private:
static const std::map<key, value> m_myMap;
static const std::map<key, value> createMyStaticConstantMap();
public:
static std::map<key, value> getMyConstantStaticMap( return m_myMap );
}; //MyClass
我的班级.cpp
#include "MyClass.h"
const std::map<key, value> MyClass::m_myMap = MyClass::createMyStaticConstantMap();
const std::map<key, value> MyClass::createMyStaticConstantMap() {
std::map<key, value> mMap;
mMap.insert( std::make_pair( key1, value1 ) );
mMap.insert( std::make_pair( key2, value2 ) );
// ....
mMap.insert( std::make_pair( lastKey, lastValue ) );
return mMap;
} // createMyStaticConstantMap
通过此实现,您的类常量静态映射是私有成员,并且可以使用公共 get 方法被其他类访问。否则 由于它是常量且无法更改,因此您可以删除公共 get 方法 并将映射变量移动到类的公共部分。然而,如果需要继承和/或多态性,我会将 createMap 方法保留为私有或受保护。以下是一些使用示例。
std::map<key,value> m1 = MyClass::getMyMap();
// then do work on m1 or
unsigned index = some predetermined value
MyClass::getMyMap().at( index ); // As long as index is valid this will
// retun map.second or map->second value so if in this case key is an
// unsigned and value is a std::string then you could do
std::cout << std::string( MyClass::getMyMap().at( some index that exists in map ) );
// and it will print out to the console the string locted in the map at this index.
//You can do this before any class object is instantiated or declared.
//If you are using a pointer to your class such as:
std::shared_ptr<MyClass> || std::unique_ptr<MyClass>
// Then it would look like this:
pMyClass->getMyMap().at( index ); // And Will do the same as above
// Even if you have not yet called the std pointer's reset method on
// this class object.
// This will only work on static methods only, and all data in static methods must be available first.
我编辑了我原来的帖子,我发布的原始代码没有任何问题,编译、构建和运行正确,只是 我作为答案提出的第一个版本是地图被声明为公共的,并且地图是 const 但不是静态的。
如果您使用的编译器仍然不支持通用初始化,或者您对使用 Boost 有保留,另一种可能的替代方案如下
std::map<int, int> m = [] () {
std::pair<int,int> _m[] = {
std::make_pair(1 , sizeof(2)),
std::make_pair(3 , sizeof(4)),
std::make_pair(5 , sizeof(6))};
std::map<int, int> m;
for (auto data: _m)
{
m[data.first] = data.second;
}
return m;
}();
您可以使用单例模式来实现此目的。
// The static pointer is initialized exactly once which ensures that
// there is exactly one copy of the map in the program, it will be
// initialized prior to the first access, and it will not be destroyed
// while the program is running.
class myClass {
private:
static std::map<int,int> myMap() {
static const auto* myMap = new std::map<int,int> {
{1, 2},
{3, 4},
{5, 6}
};
return *myMap;
}
}
然后您可以像这样使用您的地图
int x = myMap()[i] //where i is a key in the map
函数调用不能出现在常量表达式中。
试试这个:(只是一个例子)
#include <map>
#include <iostream>
using std::map;
using std::cout;
class myClass{
public:
static map<int,int> create_map()
{
map<int,int> m;
m[1] = 2;
m[3] = 4;
m[5] = 6;
return m;
}
const static map<int,int> myMap;
};
const map<int,int>myClass::myMap = create_map();
int main(){
map<int,int> t=myClass::create_map();
std::cout<<t[1]; //prints 2
}
我经常使用这个模式,推荐你也使用它:
class MyMap : public std::map<int, int>
{
public:
MyMap()
{
//either
insert(make_pair(1, 2));
insert(make_pair(3, 4));
insert(make_pair(5, 6));
//or
(*this)[1] = 2;
(*this)[3] = 4;
(*this)[5] = 6;
}
} const static my_map;
当然它的可读性不是很好,但如果没有其他库,我们能做到的最好。 此外,不会像您的尝试那样进行任何冗余操作,例如从一张地图复制到另一张地图。
这在函数内部更加有用: 而不是:
void foo()
{
static bool initComplete = false;
static Map map;
if (!initComplete)
{
initComplete = true;
map= ...;
}
}
使用以下内容:
void bar()
{
struct MyMap : Map
{
MyMap()
{
...
}
} static mymap;
}
您不仅不再需要在这里处理布尔变量,如果已经调用了函数内部静态变量的初始值设定项,您也不会检查隐藏的全局变量。