关于map的C ++下标运算符

时间:2016-09-12 13:56:54

标签: c++ dictionary stl operator-keyword

最近,我对下标操作员对地图感到困惑。例如 ,代码如下所示

#include <map>

class A{
public:
    int a;
    A(){cout << "default constructor" <<endl;}
    A(int a){
        cout << "user_defined constructor" <<endl;
        this->a = a;
    }
    A(const A& tmp){
        cout << "copy constructor" <<endl;
        this->a = tmp.a;
    }
    A& operator= (const A& tmp){
        cout << "assign constructor" <<endl;
        this->a = tmp.a;
        return *this;
    }

};
int main(){
    std::map<int, A> m;
    m[1] = A(1);  // error occur  right?
    m.insert (make_pair(1,A(1)));   // ok
}

我想知道编写代码时发生了什么。

m[1] = A(1); // it will first make a empty pair ? right? 

m.insert (make_pair(1,A())); // here call default constructor  

然后调用Assignment构造函数或复制构造函数? 输出是

user_defined constructor
default constructor
copy constructor
copy constructor
assign constructor

你能否向我解释一下细节,非常感谢。

2 个答案:

答案 0 :(得分:3)

当你写:

m[1] = A(1);

首先,地图会查找密钥为1的条目。如果它找不到,则它会尝试使用该键创建一个新条目,以及一个默认构造的A对象。由于您的A类不是默认可构造的,因此无法编译。

但假设情况并非如此,则返回对此新创建的A对象的引用(或对已存在的对象的引用,如果找到该键)。这一切都发生在m[1]表达式上。声明的其余部分= A(1)会创建一个新的A对象,并将其分配给从m[1]返回的引用。

答案 1 :(得分:1)

如果您想知道调用哪些函数,只需在调试器中设置它们的断点即可。您会看到m[1] = A(1);按顺序调用

  1. 构造函数A(int)
  2. 默认构造函数A()(必须添加以进行编译)
  3. A& operator=(const A& other)
  4. 所以发生的事情非常清楚:它首先构造你的A(1),然后在地图中搜索键1,找不到它,因此在其上插入一个默认的A,最后将其替换为你的A(1)

    介意这发生在调试版本上。发布版本可以optimized以避免上述某些操作。在这些功能中添加打印件以完全确定。

    如果您想减少副本数量,请使用m.emplace(1,1)代替m[1] = A(1)。它只会调用构造函数A(int),既不是默认构造函数,也不是赋值运算符。