关于map的C++下标运算符
C++ subscript operator about map
最近被下标运算符弄糊涂了。例如
,代码如下所示
#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
然后调用赋值构造函数或拷贝构造函数?
输出是
user_defined constructor
default constructor
copy constructor
copy constructor
assign constructor
能否详细解释一下,非常感谢
当你写:
m[1] = A(1);
首先,地图会查找关键字为 1
的条目。如果找不到,它会尝试使用该键创建一个新条目,以及一个默认构造的 A
对象。由于您的 A
class 不是默认可构造的,因此无法编译。
但假设情况并非如此,则返回对这个新创建的 A
对象的引用(或者对已经存在的对象的引用,如果找到密钥)。这一切都发生在 m[1]
表达式中。您语句的其余部分 = A(1)
创建一个新的 A
对象并将其分配给从 m[1]
.
返回的引用
如果您想知道调用了哪些函数,只需在调试器中对其设置断点即可。您会看到 m[1] = A(1);
按顺序调用
- 构造函数
A(int)
- 默认构造函数
A()
(必须添加才能编译)
A& operator=(const A& other)
所以发生的事情很清楚:它首先构造你的 A(1)
,然后在映射中搜索键 1,找不到它所以在上面插入一个默认的 A
,最后替换它由你 A(1)
.
请注意,这发生在调试版本中。发布版本可以是 optimized 以避免上面的一些操作。在那些函数中添加打印是完全确定的。
如果您想尽量减少份数,请使用 m.emplace(1,1)
而不是 m[1] = A(1)
。它只会调用构造函数A(int)
,既不会调用默认构造函数,也不会调用赋值运算符。
最近被下标运算符弄糊涂了。例如 ,代码如下所示
#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
然后调用赋值构造函数或拷贝构造函数? 输出是
user_defined constructor
default constructor
copy constructor
copy constructor
assign constructor
能否详细解释一下,非常感谢
当你写:
m[1] = A(1);
首先,地图会查找关键字为 1
的条目。如果找不到,它会尝试使用该键创建一个新条目,以及一个默认构造的 A
对象。由于您的 A
class 不是默认可构造的,因此无法编译。
但假设情况并非如此,则返回对这个新创建的 A
对象的引用(或者对已经存在的对象的引用,如果找到密钥)。这一切都发生在 m[1]
表达式中。您语句的其余部分 = A(1)
创建一个新的 A
对象并将其分配给从 m[1]
.
如果您想知道调用了哪些函数,只需在调试器中对其设置断点即可。您会看到 m[1] = A(1);
按顺序调用
- 构造函数
A(int)
- 默认构造函数
A()
(必须添加才能编译) A& operator=(const A& other)
所以发生的事情很清楚:它首先构造你的 A(1)
,然后在映射中搜索键 1,找不到它所以在上面插入一个默认的 A
,最后替换它由你 A(1)
.
请注意,这发生在调试版本中。发布版本可以是 optimized 以避免上面的一些操作。在那些函数中添加打印是完全确定的。
如果您想尽量减少份数,请使用 m.emplace(1,1)
而不是 m[1] = A(1)
。它只会调用构造函数A(int)
,既不会调用默认构造函数,也不会调用赋值运算符。