एक स्थिर एसटीडी :: मैपिंग <int, int> C ++ में


448

स्थैतिक मानचित्र को आरम्भ करने का सही तरीका क्या है? क्या हमें एक स्थैतिक फ़ंक्शन की आवश्यकता है जो इसे प्रारंभ करेगा?

जवाबों:


619

C ++ 11 का उपयोग करना:

#include <map>
using namespace std;

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

Boost.Assign का उपयोग करना :

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

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

115
जब भी मुझे C ++ के साथ ऐसा कुछ दिखाई देता है, मुझे लगता है कि सभी भयावह टेम्पलेट कोड इसके पीछे होने चाहिए। अच्छा उदाहरण!
ग्रेग हेवगिल सेप

34
इन उपयोगिताओं को लागू करने वाले सभी भयावह टेम्पलेट कोड की सुंदरता यह है कि यह बड़े करीने से पुस्तकालय में संलग्न है और अंत उपयोगकर्ता को शायद ही कभी जटिलता से निपटने की आवश्यकता होती है।
स्टीव गाइडी

45
@QBziZ: यदि आपकी कंपनी ने "मानक पर्याप्त" नहीं होने के आधार पर बूस्ट का उपयोग करते हुए गिरावट आती है, तो मुझे आश्चर्य है कि सी ++ लाइब्रेरी "मानक पर्याप्त" क्या होगा । बूस्ट है सी ++ सांकेतिक शब्दों में बदलनेवाला के लिए मानक साथी।
देवसोलर

47
बूस्ट (यहां, और अन्य जगहों पर) के साथ मेरी समस्या यह है कि आप अक्सर इसके बिना (इस मामले में C ++ 11 के साथ या फ़ंक्शन के साथ C ++ 11 से पहले ) प्राप्त कर सकते हैं। बूस्ट एक महत्वपूर्ण संकलन समय उपरि जोड़ता है, आपकी रिपॉजिटरी में पार्क करने के लिए (और अगर आप एक संग्रह बना रहे हैं / ज़िप / निकालने के लिए कॉपी करने के लिए) तो बहुत सारी फाइलें थीं। यही कारण है कि मैं इसका उपयोग नहीं करने की कोशिश करता हूं। मुझे पता है कि आप चुन सकते हैं कि किन फ़ाइलों को शामिल करना है / शामिल नहीं करना है, लेकिन आप आमतौर पर बूस्ट के स्वयं के साथ क्रॉस निर्भरता के बारे में चिंता नहीं करना चाहते हैं, इसलिए आप बस पूरी चीज की नकल करते हैं।
बॉबोबो

7
बूस्ट के साथ मेरी समस्या यह है कि इसमें अक्सर कई नए पुस्तकालय निर्भरताएं होती हैं, जिसका अर्थ है आमतौर पर अधिक पैकेज जो सही ढंग से काम करने के लिए स्थापित किए जाने की आवश्यकता होती है। हमें पहले से ही libstdc ++ की आवश्यकता है। उदाहरण के लिए, बूस्ट एएसआईओ लाइब्रेरी को कम से कम 2 नए पुस्तकालयों (शायद अधिक) की आवश्यकता होती है जिन्हें स्थापित करने की आवश्यकता होती है। C ++ 11/14 यह बूस्ट की जरूरत नहीं है एक बहुत आसान बना देता है।
रहली

135

एक समारोह का उपयोग करने का सबसे अच्छा तरीका है:

#include <map>

using namespace std;

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

map<int,int> m = create_map();

18
यह 'सर्वश्रेष्ठ' क्यों है? उदाहरण के लिए यह @ सपने देखने वाले के जवाब से बेहतर क्यों है?
लोर्ने का मार्किस

6
मुझे लगता है कि यह "सबसे अच्छा" है क्योंकि यह वास्तव में सरल है और मौजूदा अन्य संरचनाओं पर निर्भर नहीं करता है (जैसे कि बूस्ट :: असाइन या इसे लागू करना)। और @ सपने देखने वाले के उत्तर की तुलना में, ठीक है, मैं केवल एक नक्शे को शुरू करने के लिए एक पूरी संरचना बनाने से बचता हूं ...
पियरेबीडीआर

3
नोट यहाँ एक खतरा हैexternचर में इसका सही मान नहीं होगा "मुख्य रन-टाइम निर्माता से पहले" यदि कंपाइलर केवल externघोषणा को देखता है, लेकिन अभी तक वास्तविक चर परिभाषा में नहीं चला है
बॉबोबो

5
नहीं, खतरा यह है कि ऐसा कुछ भी नहीं है जिसमें कहा जाता है कि स्थिर चर को कम से कम (कम से कम संकलन इकाइयों में) आरम्भ किया जाना चाहिए। लेकिन यह इस सवाल से जुड़ी समस्या नहीं है। यह स्थिर चर के साथ एक सामान्य समस्या है।
पियरब्रेड

5
नो बूस्ट एंड नो C ++ 11 => +1। ध्यान दें कि फंक्शन को इनिशियलाइज़ करने के लिए इस्तेमाल किया जा सकता है const map<int,int> m = create_map()(और इसलिए, इनिशियलाइज़ेशन लिस्ट में एक क्लास के struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
कांस्टेबल मेंबर्स

115

यह बढ़ावा देने के लिए कुछ समान बनाने के लिए एक जटिल मुद्दा नहीं है। यहां केवल तीन कार्यों के साथ एक वर्ग है, जिसमें निर्माणकर्ता शामिल है, यह बताने के लिए कि क्या बढ़ा (लगभग)।

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

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

    operator std::map<T, U>()
    {
        return m_map;
    }
};

उपयोग:

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

उपरोक्त कोड वैश्विक चर या एक वर्ग के स्थिर सदस्यों के प्रारंभिककरण के लिए सबसे अच्छा काम करता है जिसे आरंभीकृत करने की आवश्यकता होती है और आपको इसका कोई मतलब नहीं है कि यह पहले उपयोग किया जाता है लेकिन आप यह आश्वस्त करना चाहते हैं कि इसमें मान उपलब्ध हैं।

यदि कहें, तो आपको मौजूदा std :: map ... में तत्वों को सम्मिलित करना है ... यहाँ आपके लिए एक और वर्ग है।

template <typename MapType>
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<int, int> Int2IntMap;
Int2IntMap testMap;
map_add_values<Int2IntMap>(1,2)(3,4)(5,6).to(testMap);

इसे GCC 4.7.2 के साथ यहां देखें : http://ideone.com/3uYJiH

############### हर कोई इस समय से पहले है ################

EDIT : map_add_valuesनीचे दिया गया वह वर्ग, जिसका मूल हल मैंने सुझाया था, जीसीसी 4.5+ की बात आने पर विफल हो जाएगा। मौजूदा मानचित्र में मान जोड़ने के लिए कृपया ऊपर दिए गए कोड को देखें ।


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

उपयोग:

std :: map <int, int> my_map;
// बाद में कहीं कोड के साथ
map_add_values ​​<int, int> (my_map) (1,2) (3,4) (5,6);

नोट: पहले मैंने operator []वास्तविक मूल्यों को जोड़ने के लिए उपयोग किया था । यह संभव नहीं है क्योंकि डैल द्वारा टिप्पणी की गई है।

#################### OBSOLETE खंड का अंत ####################


3
मैं संदेश के साथ त्रुटि-संख्याओं (एक एनम से) को बांधने के लिए <int, string> के रूप में आपके पहले नमूने का उपयोग कर रहा हूं - यह एक आकर्षण की तरह काम कर रहा है - धन्यवाद।
स्लैशमाईस

1
operator[]केवल एक ही तर्क लेता है।
dalle

1
@ डॉल: अच्छा कैच! किसी कारण से मुझे लगा कि ओवरलोडेड [] ऑपरेटर अधिक स्वीकार कर सकते हैं।
वाइट फाल्कन

2
यह एक शानदार जवाब है। यह शर्म की बात है कि ओपी ने कभी एक का चयन नहीं किया। आप मेगा सहारा के लायक हैं।
थॉमस थोरोगूड

map_add_values ​​gcc में काम नहीं करता है, जो शिकायत करता है: error: conflicting declaration ‘map_add_values<int, int> my_map’ error: ‘my_map’ has a previous declaration as ‘std::map<int, int> my_map’
मार्टिन वैंग

42

यहां एक और तरीका है जो 2-तत्व डेटा कंस्ट्रक्टर का उपयोग करता है। इसे आरम्भ करने के लिए किसी कार्य की आवश्यकता नहीं है। कोई 3 पार्टी कोड (बूस्ट), कोई स्थिर कार्य या ऑब्जेक्ट नहीं है, कोई चाल नहीं है, बस सरल सी ++:

#include <map>
#include <string>

typedef std::map<std::string, int> 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} };

25

उदाहरण के लिए:

const std::map<LogLevel, const char*> g_log_levels_dsc =
{
    { LogLevel::Disabled, "[---]" },
    { LogLevel::Info,     "[inf]" },
    { LogLevel::Warning,  "[wrn]" },
    { LogLevel::Error,    "[err]" },
    { LogLevel::Debug,    "[dbg]" }
};

यदि मानचित्र किसी वर्ग का डेटा सदस्य है, तो आप इसे हेडर में सीधे निम्नलिखित तरीके से (C ++ 17 के बाद से) प्रारंभ कर सकते हैं:

// Example

template<>
class StringConverter<CacheMode> final
{
public:
    static auto convert(CacheMode mode) -> const std::string&
    {
        // validate...
        return s_modes.at(mode);
    }

private:
    static inline const std::map<CacheMode, std::string> s_modes =
        {
            { CacheMode::All, "All" },
            { CacheMode::Selective, "Selective" },
            { CacheMode::None, "None" }
            // etc
        };
}; 

24

मैं मानचित्र को किसी स्थिर ऑब्जेक्ट के अंदर लपेटूंगा, और इस ऑब्जेक्ट के कंस्ट्रक्टर में मैप इनिशियलाइज़ेशन कोड डालूँगा, इस तरह आप सुनिश्चित हैं कि मैप को इनिशियलाइज़ेशन कोड निष्पादित होने से पहले बनाया जाता है।


1
मैं इस एक पर तुम्हारे साथ हूँ। यह और भी तेज है :)
QBziZ

2
तड से तेज क्या? एक शुरुआती के साथ एक वैश्विक स्थिर? नहीं, यह नहीं है (आरवीओ के बारे में याद रखें)।
पावेल मिनाएव

7
अच्छा उत्तर। मुझे खुशी होगी अगर मैं वास्तविक उदाहरण कोड
सुंगगुक लिम जूल

18

बस एक शुद्ध C ++ 98 के आसपास काम करना चाहते थे:

#include <map>

std::map<std::string, std::string> aka;

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

2
यह डिफॉल्ट कंस्ट्रक्टर के बिना ऑब्जेक्ट के लिए काम नहीं करता है, इन्सर्ट विधि को IMHO पसंद किया जाना चाहिए
एलेसेंड्रो टेरुज़ी

16

तुम कोशिश कर सकते हो:

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

1
आप C ++ 11 से पहले नॉन-एग्रीगेट प्रकारों के साथ शुरुआती सूचियों का उपयोग नहीं कर सकते हैं, इस स्थिति में आप {1, 2}इसके बजाय छोटे सिंटैक्स का उपयोग कर सकते हैं std::pair<int, int>(1, 2)
फेरुचियो

9

यह PierreBdRबिना नक़ल के समान है ।

#include <map>

using namespace std;

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

static map<int,int> m;
static bool _dummy = create_map (m);

12
यह शायद वैसे भी कॉपी नहीं किया गया होगा।
GManNickG

2
लेकिन इस तरह से नक्शा स्थिर गति नहीं हो सकता है, क्या यह हो सकता है?
xmoex 10

6

यदि आप C ++ 98 के साथ अटके हुए हैं और बूस्ट का उपयोग नहीं करना चाहते हैं, तो यहां एक समाधान है जिसका उपयोग मैं तब करता हूं जब मुझे एक स्थैतिक को शुरू करने की आवश्यकता होती है:

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 ] ) ] );

-4

आपके पास यहां कुछ बहुत अच्छे उत्तर हैं, लेकिन मैं मेरे पास हूं, यह "जब आप सभी जानते हैं कि एक हथौड़ा है" का मामला दिखता है ...

स्थैतिक मानचित्र को इनिशियलाइज़ करने का कोई मानक तरीका क्यों नहीं है, इसका सबसे सरल उत्तर यह है कि स्टैटिक मैप का उपयोग करने का कोई अच्छा कारण नहीं है ...

एक नक्शा एक संरचना है जिसे तत्वों के अज्ञात सेट के लिए तेजी से देखने के लिए डिज़ाइन किया गया है। यदि आप हाथ से पहले तत्वों को जानते हैं, तो बस एक सी-सरणी का उपयोग करें। यदि आप ऐसा नहीं कर सकते हैं, तो मानों को एक क्रमबद्ध तरीके से दर्ज करें, या उन पर सॉर्ट चलाएं। तब आप stl :: फ़ंक्शन का उपयोग करके लॉग (n) प्रदर्शन प्राप्त कर सकते हैं। जब मैंने इसका परीक्षण किया है तो वे सामान्य रूप से नक्शे से कम से कम 4 गुना तेज प्रदर्शन करते हैं।

फायदे कई गुना हैं ... - तेज प्रदर्शन (* 4, मैंने कई सीपीयू के प्रकारों को मापा है, यह हमेशा 4 के आसपास होता है) - सरल डिबगिंग। यह देखना आसान है कि रैखिक लेआउट के साथ क्या हो रहा है। - कॉपी संचालन के तुच्छ कार्यान्वयन, जो आवश्यक हो जाना चाहिए। - यह रन टाइम पर कोई मेमोरी आवंटित नहीं करता है, इसलिए कभी भी कोई अपवाद नहीं फेंकेगा। - यह एक मानक इंटरफ़ेस है, और इसलिए डीएलएल, या भाषाओं, आदि को साझा करना बहुत आसान है।

मैं आगे बढ़ सकता था, लेकिन यदि आप अधिक चाहते हैं, तो स्ट्रॉन्स्ट्रुप के कई ब्लॉगों पर नज़र न डालें।


8
प्रदर्शन मानचित्र का उपयोग करने का एकमात्र कारण नहीं है। उदाहरण के लिए, कई मामले हैं, जहां आप मूल्यों को एक साथ जोड़ना चाहते हैं (उदाहरण के लिए, एक त्रुटि संदेश के साथ एक त्रुटि कोड), और एक नक्शा उपयोग और उपयोग को सरल बनाता है। लेकिन इन ब्लॉग प्रविष्टियों के लिए एक लिंक दिलचस्प हो सकता है, शायद मैं कुछ गलत कर रहा हूं।
MatthiasB

5
यदि आप इसका उपयोग कर सकते हैं तो एक सरणी बहुत आसान है और उच्च प्रदर्शन है। लेकिन अगर सूचकांक (चाबियाँ) सन्निहित नहीं हैं, और व्यापक रूप से दूरी पर हैं, तो आपको एक नक्शे की आवश्यकता है।
कारलू

1
एक mapआंशिक कार्य (गणितीय अर्थ में कार्य; लेकिन यह भी, प्रोग्रामिंग अर्थ में, की तरह) का प्रतिनिधित्व करने के लिए एक उपयोगी रूप है। एक सरणी ऐसा नहीं करती है। आप स्ट्रिंग का उपयोग करके किसी सरणी से डेटा देखने, कह नहीं सकते।
einpoklum

3
आपका उत्तर मान्य प्रश्न का उत्तर देने का प्रयास नहीं करता है, और इसके बजाय भाषा की सीमाओं पर अटकलें लगाता है, इसलिए विभिन्न समस्याओं के समाधान का प्रस्ताव करता है, इसलिए नीचे की ओर। एक वास्तविक परिदृश्य - मैपिंग (निरंतर या नहीं) पाठ स्ट्रिंग के लिए लाइब्रेरी त्रुटि कोड। सरणी के साथ, खोज समय O (n) है, जिसे O (लॉग (n)) के स्थैतिक मानचित्रण द्वारा सुधारा जा सकता है।
तोशा

2
यदि वास्तव में "स्थैतिक मानचित्र का उपयोग करने का कोई अच्छा कारण नहीं है ..." तो यह बहुत अजीब है कि वाक्यविन्यास (शुरुआती सूचियां) जो उन्हें उपयोग करने में आसान बनाती हैं उन्हें C ++ 11 में जोड़ा गया था।
एलिस्बेन जूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.