关于地图的C ++下标运算符[关闭]
Posted
技术标签:
【中文标题】关于地图的C ++下标运算符[关闭]【英文标题】:C++ subscript operator about map [closed] 【发布时间】:2016-09-12 13:56:54 【问题描述】:最近,我对地图的下标运算符感到困惑。例如 ,代码如下所示
#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
能否详细解释一下,非常感谢。
【问题讨论】:
A
不是默认可构造的,它不能是 map
的值
@KABoissonneault:可以。在这种情况下你不能使用operator[]
。
你需要什么样的“细节”?
@KABoissonneault 如果存在 A 的默认构造函数,我们可以写成 m[1] = A(1);
@BenjaminLindley 有趣。有点像如何在向量中使用仅移动类型,而不是vector::push_back
。我觉得那些“隐式动态 API 更改”没有很好的文档记录
【参考方案1】:
当你写作时:
m[1] = A(1);
首先,map 会查找键为 1
的条目。如果找不到,它会尝试使用该键创建一个新条目,以及默认构造的A
对象。由于您的 A
类不是默认可构造的,因此无法编译。
但假设情况并非如此,则返回对这个新创建的A
对象的引用(或对已经存在的对象的引用,如果找到密钥的话)。这一切都发生在m[1]
表达式中。语句的其余部分 = A(1)
创建一个新的 A
对象并将其分配给从 m[1]
返回的引用。
【讨论】:
所以你的意思是:它会先调用A的默认构造函数,然后调用A的自定义构造函数,最后可以调用A的Assignment构造函数吗? @ArthurGeorge:是的。尽管默认构造函数调用和对A(1)
的显式调用的顺序是实现定义的。可能会颠倒过来。
感谢@Benjamin Lindley。但是当我在上面的段代码中添加一些测试代码时。输出结果为:A的用户定义构造函数->A的默认构造函数->A的拷贝构造函数->A的拷贝构造函数->A的赋值构造函数。是的,一个user_defined构造函数一个默认构造函数;两个复制构造函数;和一个分配构造函数
@ArthurGeorge:是的,可能还有未指定数量的复制构造函数调用,或者在将对象放入地图的过程中移动构造函数调用。顺便说一句,赋值运算符不是构造函数。
“未指定数量的副本”表示复制构造函数可能不是 2 ?我真的很想知道为什么有几个拷贝构造函数?有什么链接可以帮助我吗?非常感谢【参考方案2】:
如果您想知道调用了哪些函数,只需在调试器中对其设置断点即可。你会看到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)
,既不调用默认构造函数,也不调用赋值运算符。
【讨论】:
谢谢,我只是打印了一些内容,它的输出类似于 A 的用户定义构造函数 -->A 的默认构造函数 --> A 的复制构造函数 --> A 的复制构造函数 --> A 的赋值构造函数。跨度> 那么你的问题有答案了吗? 你关于使用调试器设置断点的想法真的很有帮助,顺便说一下,@Benjamin Lindley 回答了为什么有两个复制构造函数的原因。再次感谢。 注意发布版本中的复制省略(我在上面的答案中包含了一个链接),唯一确定的方法是使用打印。此外,如果您想要最少数量的构造,请使用emplace
(也在上面添加)。以上是关于关于地图的C ++下标运算符[关闭]的主要内容,如果未能解决你的问题,请参考以下文章