创建一次销毁两次?!复制构造函数的致命错误。

创建一次销毁两次?!复制构造函数的致命错误。

        C++为我们提供了默认的复制构造函数,赋值函数和析构函数,使用的全部是“浅复制”,即仅仅复制栈上的数据。换句话说,如果我们涉及到了对堆数据的操作,这些函数都必须我们自己重新来写。我很郁闷为什么在编译的时候,C++不能自己发现构造函数使用了堆操作,从而提醒不要使用默认的这三个函数。也许是因为要编译器做到智能的判断很难吧。用new...delete或许很容易看出来,但是更多的函数调用,特别是涉及到C风格的函数的时候,真的很难判断哪些函数使用到了堆操作。
        而这三个函数的作用可以说是巨大的!析构就不说了,析构可以说是C++永远的痛。复制构造函数用得最多的地方,恐怕就是成员初始化列表的时候,这几乎是在一个类成员数据使用到另外一个类对象时候的唯一方法。而赋值函数则是把数据从语句体(“{}”对,循环,判断)中带出的最简单方法——虽然我们现在可以很方便的使用vector。
        这里先说说复制构造函数吧。如果遗漏申明,又不慎用到,比如这个例子:

#include  < iostream >
#include 
< vector >

class  A
{
private :
    
int  a;
public :
    A(
int  _a): a(_a)
    {
        std::cout 
<<   " A created!\n " ;
    }
/*
    A(const A& copy): a(copy.a)
    {
        std::cout << "A copy created!\n";
    }
*/
    
~ A()
    {
        std::cout 
<<   " A destroyed!\n " ;
    }
    
void  show()  const
    {
        std::cout 
<<  a  <<  std::endl;
    }
};

int  main( int  argc,  char *  argv[])
{
    A a(
1 );
    A b(a);

    
return   0 ;
}
那么,结果运行就会出现貌似创建一次,但是却销毁了两次的假象。这当然是不可能发生的,但是郁闷的是,C++中的构造和析构不总是成对出现的,比如我们前面说到的手动显式调用析构函数的情况。所以,如果放在大的项目中,这为我们的调试带来更多的困难。
        所以,结论是,如果A类构造具有堆操作,有可能把A类作为B类的成员数据,B类又有可能通过成员初始化列表构造A对象,请一定别忘记手写复制构造函数。

你可能感兴趣的:(创建一次销毁两次?!复制构造函数的致命错误。)