#include "stdafx.h"
#include <map>using namespace std;class Test
{
public:
Test(int a);
Test();
Test(const Test &t); int m_a;
};Test::Test(int a)
{
m_a = a;
cout<<"Test(int a)"<<endl;
}Test::Test()
{
cout<<"Test()"<<endl;
}Test::Test(const Test &t)
{
m_a = 1;
cout<<"Test(Test &t)"<<endl;
}typedef map<int, Test> TM;int _tmain(int argc, _TCHAR* argv[])
{
TM tm;
Test t(3);
tm[1] = t; cout<<tm[1].m_a<<endl;
return 0;
}
结果:
Test(int a)
Test()
Test(Test &t)
Test(Test &t)
3这段代码运行结果显示调用了2次拷贝构造函数Test(const Test &t),分别在哪里调用的?
为什么我拷贝构造函数已经将m_a=1了,但是输出结果还是3?

解决方案 »

  1.   

    TM tm;
        Test t(3);
        tm[1] = t;    cout<<tm[1].m_a<<endl;我靠,楼主自己输出的3,还问为什么
      

  2.   

    调试的时候发现:
    tm[1] = t;
    在这句分别调用了
    Test()
    Test(Test &t)
    Test(Test &t)
    请问这是为什么?
      

  3.   


    这里tm[1] = t;是向map里插入一个新的pair, 调用默认构造函数Test()创建一个新的Test对象是肯定的,至于为什么调用了两次拷贝构造函数,不清楚map的函数是怎么实现的,估计是用了值传递吧, 最后这个map里的test对象的m_a因赋值操作是3可以用F11跟进去看看map里的实现
      

  4.   

    跟踪一下就知道原因了,
    TM tm;
    Test t(3);    //输出Test(int a)
    tm[1] = t;    //在[1]不存在的时候他会执行tm.insert(TM::value_type(1, Test()));
                  //里面Test()输出Test()
                  //TM::value_type实际上是一个std::pair,这里将1和Test()作为参数给他构造会调用
                    //到std::pair::second(const Test&),而second就是Test类型,因此有一次
                    //Test(Test &t),然后这个std::pair传给insert做参数,内部会拷贝构造一个
                    //std::pair,也就间接的拷贝构造了Test,于是有第二个(Test &t)。
    cout<<tm[1].m_a<<endl;    //前一句调用的是operator=,调用的是默认赋值函数,所以复制了的m_a还是3。
      

  5.   

    为避免歧义,多解释一下“然后这个std::pair传给insert做参数,内部会拷贝构造一个std::pair”,这个不是说因为做参数导致拷贝构造(因为insert的参数是传引用的),而是tm在保存这个参数值的时候,会有一次拷贝构造。
      

  6.   


        Test t2=t;
        Test t3;
        t3=t;LZ加上这几行就会明白了。
    t3=t不会使用Test::Test(const Test &t)函数,如果没有重载=运算符,C++按照默认的赋值操作,把t的m_a复制到t3中。
    Test::Test(const Test &t)只在对象初始化的时候使用,比如上面的Test t2=t(或者Test t2(t)),上tm[1]=t显然是先进行了初始化操作,最后再按赋值操作进行。