我正在用C ++ 11开发一个程序,我需要在两个类中使用C ++ STL映射。 在使用的2个位置中,地图具有相同的键和值列表。
这些类用于程序的不同部分:
// in other part of the program
void check_something()
{
// the size of the list can be 100, 200 or ...
map<string, string> amap{
{"something", "nothing"},
{"key", "value"},
};
SameClass sc{amap};
// use sc
}
// in other part of the program
void check_other_thing()
{
// the size of the list can be 100, 200 or ...
map<string, string> amap_2{
{"something", "nothing"},
{"key", "value"},
};
SameClass sx{amap_2};
// use sx
}
现在这可以(用于测试),但我想知道(用于维护和优化)如何声明和定义一次,然后在程序中的任何地方使用地图?
我是否需要创建一个将地图放在shared_ptr&lt;&gt;中的类或结构或函数?并返回地图?
我不想使用全局变量!
答案 0 :(得分:1)
如果您想在程序中使用变量WHEREVER,我们就会谈论您不想使用的全局变量(这很好!)。
另一种方法是使用静态变量创建类,它类似于全局变量,但不会创建名称冲突
float var = Variables::numba
您可以像void setMap(map<string, string> &map) //note ampersand, it has to be a reference
{
mMap = map //where mMap means member variable in your class
}
您还可以让函数返回对您的变量的引用,然后将其存储为指针。这实际上是更好的主意,因为你不会使用任何类型的全局变量。
因此,在某处创建地图并将其传递给对象
{{1}}
如果您希望所有SameClass对象使用完全相同的映射,请将其设为静态变量。
答案 1 :(得分:1)
正如许多评论者所建议的那样,常量全局变量没有任何问题。如果Globals是可变的,它们只是问题。既然你说数据永远不会改变,那么只需将它们变成const
全局变量即可。但是,由于它们具有复杂的构造函数,如果它们不是函数局部静态函数,则会遇到static initialization order fiasco。因此修复程序如下所示:
File1:
const map<string, string>& amap() {
static const map<string,string> v {
{"something", "nothing"},
{"key", "value"},
};
return v;
}
File2(或者标题)
const map<string, string>& amap();
答案 2 :(得分:0)
您的地图似乎包含一种配置数据。我理解:
我建议您使用简单的dbconfig
类来解决第一个问题:
class dbconfig {
static map<string, string> amap; // satic: there's only one of it
public:
operator const map<string,string>& () const
{ return amap; }
// may be some functions to maintain the map
};
map<string, string> dbconfig::amap{ // there's only one such map
{"something", "nothing"}, // and it's only viisble in dbconfig
{"key", "value"}, // so totally protected
};
诀窍是使用转换运算符,它只返回一个只读常量。所以你可以在程序的任何地方使用它,就像:
dbconfig cfg; // local variable. You don't have to worry about it
SameClass sc{ cfg }; // it whill be automatically converted in a reference to
// your single static map.
优点是您的配置确实封装在对象中。因此,您可以定义一些成员来管理您的地图(添加或删除键)。
由于地图不是直接对外部可见,而是仅通过操作员,因此您可以让dbconfig对象的内部管理发展,而无需使用它来更改代码。例如,您可以在程序启动时将地图保持为空,并在第一次请求时从配置文件或其他任何内容加载数据。
然而,有一个重要的开放性问题:每个使用对象是否都有自己的地图副本,还是应该引用单个dbconfig
地图?
其他说法:您是否设想动态更改地图内容,并希望所有对象都使用最新版本?
根据答案,您可以定义用户类以保留自己的地图副本:
class SameClass {
map<string, string> mine;
public:
SameClass (const map<string, string>& m) : mine(m) { // const ref, but local copy
...
};
或继续使用参考:
class SameClass {
const map<string, string> & mine; // refers to the original. No own copy
public:
SameClass (const map<string, string>& m) : mine(m) { // const ref ...
};
};
答案 3 :(得分:0)
经过一周的尝试,我终于解决了这个问题!
感谢所有回答的人,我根据他们的想法找到问题的解决方案。
我创建一个新的头文件并将其命名为SetMap.hpp,这里是代码:
#ifndef SETMAP_HPP
#define SETMAP_HPP
#include <map>
#include <string>
struct SetMap
{
const std::map<std::string, std::string> mymap{
{"KEY_HERE","VALUE_HERE"},
};
};
#endif // SETMAP_HPP
然后,只要我需要在程序中并初始化结构,我就会包含此标题:
#include "SetMap.hpp"
SetMap sm;
// use as sm.mymap;
SameClass sx{sm.mymap};
SameClass的构造函数接受const映射引用,如下所示:
SameClass (const map<string, string> &m);
当我需要编辑键或值时(因为这个地图就像数据库一样,在我的程序中),我只需要在一个地方编辑标题SetMap.hpp。
这样,就没有使用全局变量,因为变量&#39; mymap&#39;在结构的范围内。
这里不需要类,因为对象很小,默认情况下结构的变量是公共的。此外,如果需要添加相同&#34;概念的其他变量&#34; - 定义并声明一次 - 在需要时使用,只需将其添加到结构中。
感谢所有花时间帮助我的人!