C++ 为什么不是';在这里使用map调用构造函数时,是否会像我期望的那样复制构造函数?

C++ 为什么不是';在这里使用map调用构造函数时,是否会像我期望的那样复制构造函数?,c++,destructor,stdmap,C++,Destructor,Stdmap,我在将自定义类与std::map一起使用时遇到问题。该类为成员动态分配内存,我不想在映射中使用指针,因为我想确保该类负责删除所有分配的内存。但我遇到的问题是,在我将项添加到映射之后,当代码块超出范围时,将调用objects析构函数,即使它仍然在映射上。我在下面编了一段假代码,说明了我的意思。输出是:那么问题是为什么调用最终析构函数?提前谢谢,很抱歉问了这么长的问题 Constructor Called Num:0034B7E8 Default Constructor Called Num:000

我在将自定义类与std::map一起使用时遇到问题。该类为成员动态分配内存,我不想在映射中使用指针,因为我想确保该类负责删除所有分配的内存。但我遇到的问题是,在我将项添加到映射之后,当代码块超出范围时,将调用objects析构函数,即使它仍然在映射上。我在下面编了一段假代码,说明了我的意思。输出是:那么问题是为什么调用最终析构函数?提前谢谢,很抱歉问了这么长的问题

Constructor Called Num:0034B7E8
Default Constructor Called Num:00000000
Copy Constructor Called Num:CCCCCCCC
Copy Constructor Called Num:CDCDCDCD
destructor called Num:CCCCCCCC
destructor called Num:00000000
destructor called Num:0034B7E8
Inserted Num:0034B7E8



class myClass
{
public:
  myClass(int num) 
  {
     mnNum = new int();
     cout << "Constructor Called Num:" << mnNum << endl;
   }

   myClass() : mnNum(NULL)
   {
      cout << "Default Constructor Called Num:" << mnNum << endl;
   }

   myClass(const myClass &copy) 
   {
      mnNum = new int(copy.mnNum);
      cout << "Copy Constructor Called Num:" << mnNum << endl;
   }

   ~myClass()
   {
      delete mnNum;
      mnNum = NULL;
   }

   int* mnNum;

 };

 map<string,myClass> mvMyMap;

 void testFunction()
 {
     myClass lcObj(1);

     mvMyMap["Test"] = lcObj;
 }


 int _tmain(int argc, _TCHAR* argv[])
 {
     testFunction();
     cout << "Inserted Num:" << mvMyMap["Test"].mnNum << endl;
 return 0;
  }
名为Num:0034B7E8的构造函数
名为Num:00000000的默认构造函数
名为Num:cccc的复制构造函数
名为Num:cdcdcd的复制构造函数
名为Num:cccc的析构函数
名为Num:00000000的析构函数
名为Num:0034B7E8的析构函数
插入编号:0034B7E8
类myClass
{
公众:
myClass(整数)
{
mnNum=newint();

cout构造函数忽略
num
参数,并且从不从中初始化
mnNum
。它应该如下所示:

myClass(int num) 
{
    mnNum = new int(num);
    cout << "Constructor Called Num:" << mnNum << endl;
}
myClass(int-num)
{
mnNum=新整数(num);

cout
myClass
除了复制构造函数之外,还需要一个自定义赋值运算符。因此,当您进行赋值时,您将泄漏左侧的原始值,并最终双重删除右侧的值。

很好。实际上,智能指针可能是最好的方法。这可能意味着cla中的智能指针ss,或者只是在映射中存储一个指向类的智能指针。是的,我忘记了三条规则,即当我有一个复制构造函数和析构函数时,我应该有一个赋值运算符。Plase,post real code。您当前的代码是假的。它至少不会编译
mnNum=new int(copy.mnNum)
语句。没有必要将析构函数设置为虚拟的,除非这是一个多态基类。事实并非如此。@Mike,如果您不允许继承,那么我同意不需要虚拟析构函数。但是,代码当前允许虚拟析构函数。如果您想省略虚拟的,那么我相信您也应该这样做修改代码以防止继承。没有密封的
,但有等效的方法。类具有值语义(即,它是可复制和可分配的)而且没有虚拟函数,因此不能用作多态基类。如果有人做了愚蠢的事情,添加虚拟析构函数只会使错误的代码变得不同。@Mike,我同意这个类不应该从中继承。不过,在某些情况下,我们希望从缺少虚拟方法的基类继承这些是罕见的,但这不是其中之一。在这些情况下,我们希望虚拟析构函数能够防止泄漏。在这种情况下,我们只是想让继承变得不可能。对于技术,请看,您确实不想跳出障碍,试图阻止人们故意滥用该类,特别是在它会导致运行时成本的情况下。别管它作为一个具有值语义的独立非多态类型,并相信人们会明智地使用它(如果你不信任他们,也可以添加注释)。从这样的类型继承并不一定是错误的,即使你(或我)想不出有效的理由。如果你也删除了错误的类型,这只是一个错误。
myClass(const myClass &copy) 
{
    mnNum = new int(*copy.mnNum);
    cout << "Copy Constructor Called Num:" << mnNum << endl;
}