当前位置:  开发笔记 > 编程语言 > 正文

在C++中初始化静态std :: map <int,int>

如何解决《在C++中初始化静态std::map<int,int>》经验,为你挑选了10个好方法。

初始化静态地图的正确方法是什么?我们需要一个初始化它的静态函数吗?



1> Ferruccio..:

使用C++ 11:

#include 
using namespace std;

map m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};

使用Boost.Assign:

#include 
#include "boost/assign.hpp"
using namespace std;
using namespace boost::assign;

map m = map_list_of (1, 'a') (3, 'b') (5, 'c') (7, 'd');


每当我看到像C++这样的东西时,我就会想到必须背后的所有可怕的模板代码.好例子!
@QBziZ:如果你的公司拒绝使用Boost,因为它不够"标准",我想知道C++库*会"足够标准".Boost是C++编码器的*标准伴侣.
我在Boost(这里和其他地方)的问题是,你可以经常在没有它的情况下继续使用(在这种情况下使用C++ 11或在C++ 11之前[带有函数](http://stackoverflow.com/a/)十一万一千三百零七分之十三万八千六百三十三)).Boost增加了大量的编译时间开销,有大量文件驻留在您的存储库中(如果您要进行存档,则必须复制/ zip/extract).这就是我尝试不使用它的原因.我知道你可以选择要包含/不包含的文件,但是你通常不想担心Boost与它自身的交叉依赖关系,所以你只需复制整个事物.
实现这些实用程序的所有可怕模板代码的优点在于它整齐地封装在库中,最终用户很少需要处理复杂性.
我对Boost的问题在于它经常有几个新的库依赖项,这通常意味着需要安装更多的软件包才能正常工作.我们已经需要libstdc ++了.例如,Boost ASIO库需要至少2个需要安装的新库(可能更多).C++ 11/14确实使得不需要Boost变得容易多了.
它"基本上"实现为重载运算符,但如果您遇到语法错误,请享受该行代码.它可以提供15种不同的.hpp,可能需要一两分钟的时间.有趣的代码?用它; 否则,考虑时间/大小的成本.
提升很棒.在那里很棒的东西.在我的情况下的问题:我们不能将其用作公司指南.不够标准,对普通开发人员来说不够容易(不是我的措辞).
@DevSolar我想更多地使用boost,但它与C++ 11的协同作用很糟糕,并且有一些相当...... _curious_设计决策(Iostreams要求设备可以复制,但是使流不可复制......哦,和也是不可移动的 - 至少在我正在使用的实现中,也许他们修复了它?).

2> PierreBdR..:

最好的方法是使用一个功能:

#include 

using namespace std;

map create_map()
{
  map m;
  m[1] = 2;
  m[3] = 4;
  m[5] = 6;
  return m;
}

map m = create_map();


为什么这是"最好的"?为什么例如它比@Dreamer的答案更好?
我认为这是"最好的",因为它非常简单并且不依赖于其他现有结构(例如Boost :: Assign或它的重新实现).与@ Dreamer的答案相比,我避免仅为初始化地图创建整个结构......
不,危险在于没有什么可以说静态变量的初始化顺序(至少在编译单元之间).但这不是与这个问题相关的问题.这是静态变量的一般问题.
没有提升,没有C++ 11 => +1.请注意,函数可用于初始化`const map m = create_map()`(因此,初始化初始化列表中类的const成员:`struct MyClass {const map m ; MyClass();}; MyClass :: MyClass():m(create_map())`
[注意这里存在危险](http://bobobobo.wordpress.com/2013/06/01/extern-variable-always-0/).`extern`变量在这个"主运行时构造函数之前"中没有正确的值_如果编译器只看到`extern`声明,但还没有碰到实际的变量定义_.

3> Vite Falcon..:

制作类似于提升的东西并不是一个复杂的问题.这是一个只有三个函数的类,包括构造函数,用于复制boost所做的(几乎).

template 
class create_map
{
private:
    std::map m_map;
public:
    create_map(const T& key, const U& val)
    {
        m_map[key] = val;
    }

    create_map& operator()(const T& key, const U& val)
    {
        m_map[key] = val;
        return *this;
    }

    operator std::map()
    {
        return m_map;
    }
};

用法:

std::map mymap = create_map(1,2)(3,4)(5,6);

上面的代码最适合初始化全局变量或需要初始化的类的静态成员,并且您不知道何时首先使用它,但您想确保其中的值可用.

如果说,你必须在现有的std :: map中插入元素......这里是你的另一个类.

template 
class map_add_values {
private:
    MapType mMap;
public:
    typedef typename MapType::key_type KeyType;
    typedef typename MapType::mapped_type MappedType;

    map_add_values(const KeyType& key, const MappedType& val)
    {
        mMap[key] = val;
    }

    map_add_values& operator()(const KeyType& key, const MappedType& val) {
        mMap[key] = val;
        return *this;
    }

    void to (MapType& map) {
        map.insert(mMap.begin(), mMap.end());
    }
};

用法:

typedef std::map Int2IntMap;
Int2IntMap testMap;
map_add_values(1,2)(3,4)(5,6).to(testMap);

请在此处查看GCC 4.7.2:http://ideone.com/3uYJiH

###############以下一切已经过时#################

编辑:map_add_values下面的类,这是我建议的原始解决方案,在GCC 4.5+时会失败.请查看上面的代码,了解如何向现有地图添加值.

template
class map_add_values
{
private:
    std::map& m_map;
public:
    map_add_values(std::map& _map):m_map(_map){}
    map_add_values& operator()(const T& _key, const U& _val)
    {
        m_map[key] = val;
        return *this;
    }
};

用法:

std::map my_map;
// Later somewhere along the code
map_add_values(my_map)(1,2)(3,4)(5,6);

注意:以前我用a operator []来添加实际值.dalle评论说这是不可能的.

#####################结束部分的结束#####################


我正在使用你的第一个样本作为来将错误数字(来自枚举)与消息绑定 - 它就像一个魅力 - 谢谢你.
这是一个很棒的答案.OP从未选择过,这是一种耻辱.你值得拥有大型道具.

4> Brian Neal..:

这是使用2元素数据构造函数的另一种方法.初始化它不需要任何函数.没有第三方代码(Boost),没有静态函数或对象,没有技巧,只是简单的C++:

#include 
#include 

typedef std::map MyMap;

const MyMap::value_type rawData[] = {
   MyMap::value_type("hello", 42),
   MyMap::value_type("world", 88),
};
const int numElems = sizeof rawData / sizeof rawData[0];
MyMap myMap(rawData, rawData + numElems);

自从我写这个答案后,C++ 11就出来了.您现在可以使用新的初始化列表功能直接初始化STL容器:

const MyMap myMap = { {"hello", 42}, {"world", 88} };



5> Drealmer..:

我将地图包装在静态对象中,并将地图初始化代码放在此对象的构造函数中,这样您就可以确保在执行初始化代码之前创建地图.


很好的答案.如果我看到实际的示例代码,我会很高兴
比什么快?带初始值设定项的全局静态?不,它不是(记住RVO).

6> isnullxbh..:

例如:

const std::map g_logLevelsDescriptions =
{
    { LoggerLevel::llNothing, "Logging disabled"            },
    { LoggerLevel::llInfo,    "Base information"            },
    { LoggerLevel::llWarn,    "Warnings"                    },
    { LoggerLevel::llError,   "Errors"                      },
    { LoggerLevel::llDebug,   "All information: debug-mode" }
};



7> 小智..:

只是想分享纯C++ 98的工作原理:

#include 

std::map aka;

struct akaInit
{
    akaInit()
    {
        aka[ "George" ] = "John";
        aka[ "Joe" ] = "Al";
        aka[ "Phil" ] = "Sue";
        aka[ "Smitty" ] = "Yando";
    }
} AkaInit;


这对于没有默认构造函数的对象不起作用,插入方法应该是首选恕我直言

8> 小智..:

你可以试试:

std::map  mymap = 
{
        std::pair  (1, 1),
        std::pair  (2, 2),
        std::pair  (2, 2)
};



9> eduffy..:

这类似于PierreBdR,没有复制地图.

#include 

using namespace std;

bool create_map(map &m)
{
  m[1] = 2;
  m[3] = 4;
  m[5] = 6;
  return true;
}

static map m;
static bool _dummy = create_map (m);


它可能不会被复制.
...因为(N)RVO:http://en.wikipedia.org/wiki/Return_value_optimization
但这种方式映射不能是静态const,不是吗?

10> Emanuele Ben..:

如果您不熟悉C++ 98并且不想使用boost,那么我需要初始化静态映射时使用的解决方案:

typedef std::pair< int, char > elemPair_t;
elemPair_t elemPairs[] = 
{
    elemPair_t( 1, 'a'), 
    elemPair_t( 3, 'b' ), 
    elemPair_t( 5, 'c' ), 
    elemPair_t( 7, 'd' )
};

const std::map< int, char > myMap( &elemPairs[ 0 ], &elemPairs[ sizeof( elemPairs ) / sizeof( elemPairs[ 0 ] ) ] );

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有