zoukankan      html  css  js  c++  java
  • C++对象的拷贝与赋值操作

     转:

     我的一个同事在用C++编写一个类时,知道什么时候需要实现拷贝构造函数赋值操作,但不知道什么时候拷贝构造函数被调用,什么时候赋值操作被调用,甚至把二者混为一谈。

    要弄明白这个问题,最简单的做法莫过于写个测试程序试一下。不过那样做也未必是好办法,实验的结果往往导致以偏概全的结论。不如好好想一下,弄清楚其中的原理,再去写程序去验证也不迟。

    拷贝构造函数,顾名思义,等于拷贝 + 构造它肩负着创建新对象的任务,同时还要负责把另外一个对象拷贝过来。比如下面的情况就调用拷贝构造函数:

    1. cstring str = strother; 

    赋值操作则只含有拷贝的意思,也就是说对象必须已经存在。比如下面的情况会调用赋值操作。

    1. str = strother; 

    不过有的对象是隐式的,由编译器产生的代码创建,比如函数以传值的方式传递一个对象时。由于看不见相关代码,所以不太容易明白。不过我们稍微思考一下,就会想到,既然是根据一个存在的对象拷贝生成新的对象,自然是调用拷贝构造函数了。

    两者实现时有什么差别呢?我想有人会说,没有差别。呵,如果没有差别,那么只要实现其中一个就行了,何必要两者都实现呢?不绕圈子了,它们的差别是:

    拷贝构造函数对同一个对象来说只会调用一次,而且是在对象构造时调用。此时对象本身还没有构造,无需要去释放自己的一些资源。而赋值操作可能会调用多次,你在拷贝之前要释放自己的一些资源,否则会造成资源泄露。

    参考:http://developer.51cto.com/art/201107/272737.htm

    #include<iostream>
    typedef int Name;
    using namespace std;
    class Table{
    
        Name * p;
        size_t sz;
    
        public:
    
        Table(size_t s = 15){ p = new Name[sz=s]; cout<<"construct"<<endl; }
        ~Table()
        {
            delete[]p ;
            cout<<"destructor"<<endl;
        }
    
    };
    
    void h()
    {
    Table t1; //调用一次构造函数
    Table t2 = t1;
    Table t3; //调用一次构造函数。
    t3 = t2;
    }
    
    int main()
    {
        h();
    }

       size_t是标准C库中定义的,应为unsigned int(macro 定义)。用下标访问元素时,vector使用vector::size_type作为下标类型,而数组下标的正确类型则是size_t。

    在h()结束时,默认构造函数调用了2次,而析构函数被调用了3次,为何?

    Table t1; 调用1次默认构造函数

    Table t2 = t1;默认的对象的赋值操作,按成员赋值,其中关于指针p,仅仅是将t1.p赋值给t2.p,即t2.p = t1.p,并无内存分配。对象t1和t2的p指针均指向同一块内存。

    Table t3; 调用1次默认构造函数

    t3 = t2; 原t3.p指针被t2.p覆盖,此时t3.p同样指向对象t1和t2的p指针的同一块内存。注意:t3原分配给p的内存由于没有指针指向,无法利用,造成存储浪费。

    h()结束,对象t1,t2,t3的析构函数调用,此时对t1,t2,t3的指针p所指的同一块存储进行了三次删除,非常危险,导致的结果是无发预料的,很可能灾难性的。

      因此明确定义类的复制构造函数(拷贝构造函数)和赋值预算可避免这样的错误。

    Table::Table (const Table &t)
    {
    p = new Name[sz=t.sz];
    for(int i=0;i<sz;i++) p[i]=t.p[i];
    }
    
    Table & Table::operator=(const Table &t)
    {
    if(this!=&t){
    delete []p;
    p = new Name[sz=t.sz];
    for(int i=0;i<sz;i++) p[i]=t.p[i];
    }
    return *this;
    }

    详见《C++程序设计语言-特别版》page 219

     

  • 相关阅读:
    背包解法
    第十六周周总结
    软件工程个人课程总结
    学期课后个人总结
    spring事务
    梦断代码03
    团队冲刺的第二十四天
    第十五周周总结
    百度输入法评价
    找到水王
  • 原文地址:https://www.cnblogs.com/youxin/p/2502289.html
Copyright © 2011-2022 走看看