关于地图的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&amp; operator=(const A&amp; 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 ++下标运算符[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

关于C程序中main()函数参数的使用

C语言中的一个编程问题

3前端知识总结--关于字符串的方法

关于多维数组的注意事项

关于VB数组的一个简单问题

C语言问题 怎么做?