C ++ STL map in the [] when a pit operator to use

Foreword

Learning C ++, since the discovery of the map the structure of the future, they are deeply attracted this way of key-value pairs, write code is also gradually inseparable from this structure, the chance discovery that there is a map []operation character, seem to have discovered the New World, like, write code more convenient, not knowing a deep pit is waiting in front of me.

problem

A start time to learn to use the map or the law-abiding, insertion and deletion functions, such as defining a map, first introduced the header file and namespace:

#include <map>
using namespace std;

map<int, int> mapTest;

Above it is easy to define the structure of a map object is an integer integer to another map, which maps what use is it? Here is a simple example, this mapping can be used as student numbers and the correspondence between school achievement, so long as we know student number, you can directly obtain the corresponding score easily from the map.

The most commonly start learning when you insert the following two ways:

mapTest.insert(map<int, int>::value_type(1001, 100));
mapTest.insert(make_pair(1002, 98));

But learned mapof the []subsequent operator, the above code can be written:

mapTest[1001] = 100;
mapTest[1002] = 98;

Find a need to use the time element find()function is generally written

map<int, int>::const_iterator itor = mapTest.find(1001);
if (itor != mapTest.end())
    return itor->second;

But learned mapof the []subsequent operator, said code can be abbreviated as:

return mapTest[1001];

In particular, when inserting an element, such as for counting, every time adding 1 to a value corresponding to the key, can be directly written:

mapTest[1001] += 1;

There is no need to check 1001this key is present, use the []operator will first before using the default to 0, and then perform the +1operation, this ratio before using find()Find, and then +1the operation before inserting more convenient.

In fact, this is only the use of mapa grammatical structure of sugar, but it'd be great to make a syntactic sugar, too sweet to pass up, so I mouth piece of sugar fell into the hole, because the call mapcan sometimes cause side effects If a key is not to find mapthe will in mapinsert the default value in the corresponding location of the key, let's look at an example to understand.

Testing process

Test code compiled to run in VS2015, C ++ 11 standard, if the compiler can not look at the right environment is different, try to modify the code to implement the example test also mentioned above, use mapto store student number and scores a correspondence relationship, the following simple implementation of a class to describe the relationship:

Write test classes

#include <map>
#include <iostream>
#include <algorithm>
using namespace std;

class CReportCard
{
public:
    CReportCard() { m_mapStuNo2Score.clear(); }
    ~CReportCard() { m_mapStuNo2Score.clear(); }
public:
    void LoadScores(); // 模拟录入成绩
    int  GetScoreByStudentNo(const int nStudentNo); // 根据学号查询成绩
    void PrintReportCard(); // 打印成绩单
private:
    map<int, int> m_mapStuNo2Score;
};

void CReportCard::LoadScores()
{
    m_mapStuNo2Score[1001] = 99;
    m_mapStuNo2Score[1002] = 94;
    m_mapStuNo2Score[1004] = 89;
    m_mapStuNo2Score[1005] = 92;
    m_mapStuNo2Score[1007] = 80;
}

int CReportCard::GetScoreByStudentNo(const int nStudentNo)
{
    return m_mapStuNo2Score[nStudentNo];
}

void CReportCard::PrintReportCard()
{
    cout << "show report card start----->" << endl;
    std::for_each(m_mapStuNo2Score.begin(), m_mapStuNo2Score.end(), [](std::map<int, int>::reference socrepair)
    {
        std::cout << socrepair.first << "'s score = " << socrepair.second << "\n";
    });
    cout << "show report card end<------" << endl;
}

This class is very simple, mapobject type m_mapStuNo2Scorecorrespondence relationship storing student number and performance of LoadScores()functions using []operators to mapinsert elements, simulation results entry process; GetScoreByStudentNo()function also uses the []operator simulation result inquiry procedure; PrintReportCard()function traverses the mapprint report card information.

Seemingly normal call

Then write a function to use this class, test as follows:

int main(int argc, char* argv[])
{
    CReportCard obj;
    obj.LoadScores();

    cout << "student no = 1001, score = " << obj.GetScoreByStudentNo(1001) << endl;
    cout << "student no = 1004, score = " << obj.GetScoreByStudentNo(1004) << endl;

    obj.PrintReportCard();

    return 0;
}

First, call the LoadScores()function to load the data, and then GetScoreByStudentNo()to find the number as a function of school 1001and 1004two student achievement, the last print of your transcript, let's look at the results:

student no = 1001, score = 99
student no = 1004, score = 89
show report card start----->
1001’s score = 99
1002’s score = 94
1004’s score = 89
1005’s score = 92
1007’s score = 80
show report card end<------

These results normal printing out the scores and transcripts queries, everything looks no problem, student number if the query does not exist then what will happen then?

Call of problems

Modify the above test functions, the student number change value does not exist, modified as follows:

int main(int argc, char* argv[])
{
    CReportCard obj;
    obj.LoadScores();

    cout << endl;
    cout << "student no = 1011, score = " << obj.GetScoreByStudentNo(1011) << endl;
    cout << "student no = 1014, score = " << obj.GetScoreByStudentNo(1014) << endl;

    obj.PrintReportCard();

    return 0;
}

Most of the content has not changed, only the student number into a situation that does not exist, the test results are as follows:

student no = 1011, score = 0
student no = 1014, score = 0
show report card start----->
1001’s score = 99
1002’s score = 94
1004’s score = 89
1005’s score = 92
1007’s score = 80
1011’s score = 0
1014’s score = 0
show report card end<------

Student ID does not exist in the corresponding scores of 0, it should also be said that in the past, because the key does not exist, so mapuse []when operators look to find the key to return to the default value of 0 integer does not exist, but in print results single time actually more than two, which fully exposed the []side effects that may arise operator.

When looking for return, []the operator does not correspond to the type of return can not find the default value would be finished, but also to find the keys and defaults as a pair, are inserted into unknown origin map, this operation generally we do not need, so when you clearly do not need this side effect, look for mapelements do not use the []operator.

Remedy the situation

Speaking of the above, []the operator can not find on the insert side effects generally we do not use, so when looking for or using the find()function of some more standardized, modify GetScoreByStudentNo()functions as follows:

int CReportCard::GetScoreByStudentNo(const int nStudentNo)
{
    //return m_mapStuNo2Score[nStudentNo];
    map<int, int>::const_iterator itor = m_mapStuNo2Score.find(nStudentNo);
    return itor != m_mapStuNo2Score.end() ? itor->second : 0;
}

Examples of this case run above normal, the transcripts can not be inserted into the invalid value.

to sum up

  1. mapThe []operators have side effects, when a key that does not exist, the default value will be inserted in the corresponding key position
  2. Always keep a clear mind, too convenient may give yourself buried deep pit
  3. Reverence for nature, reverence for life, the fear of every line of code you wrote
Published 150 original articles · won praise 277 · views 530 000 +

Guess you like

Origin blog.csdn.net/shihengzhen101/article/details/103529462