拷贝构造函数、赋值函数浅析

来源:互联网 发布:can数据帧的格式结构 编辑:程序博客网 时间:2024/05/22 01:59

注:以下为阅读网络上以及书上的相关内容后,自己总结的结果。因参考资料众多,无法附上链接,在此抱歉。

一个类A,如果什么都不编写,c++编译器将自动为A产生四个默认的函数(实际上还有两个,在此不列出),即:

函数 名称 A(void) 1、默认无参数构造函数 A(const A &a) 2、默认拷贝构造函数 ~A(void); 3、默认的析构函数 A & operator = (const A &a); 4、默认的赋值函数


对于构造函数和析构函数我们都了解。那么拷贝构造函数赋值函数是什么呢?

一、基本概念

1、拷贝构造函数:(也叫复制构造函数)

拷贝构造函数是C++独有的,它是一种特殊的构造函数,简单地说,是用来初始化另一个类对象的函数。

当没有重载拷贝构造函数时,即没有在类里面重写拷贝构造函数时,通过默认拷贝构造函数来创建一个对象:

class A {public:     A(A& x)        // 第一种形式    A(const A& x)  // 第二种形式    A(A& x, int a = 0, int b = 1…) // 第三种形式};A a;A b(a);   // 这里b对象还没有存在,是用 a 对象来构造和初始化 b 的!          // 第一种写法A b=a;    // 第二种写法

2、赋值函数:

当一个类的对象向该类的另一个对象赋值时,就会用到该类的赋值函数。

当没有重载赋值函数时,通过默认赋值函数来进行赋值操作:
(赋值函数本质是赋值操作符,重载赋值函数即重写赋值操作符

class A {    //……};A a;A b;    // 这里b对象是已经存在的,是用 a 对象来赋值给 b 的!b=a; 

二、为何要自己重写

既然系统能自动生成这些函数,为什么还需要自定义?

最重要的原因是:默认的拷贝构造函数 和 默认的赋值函数 均采用 位拷贝 而非 值拷贝。

位拷贝 拷贝的是地址,而 值拷贝 拷贝的是内容
位拷贝 == 浅拷贝 == 按位拷贝
值拷贝==深拷贝 == 按值拷贝

浅拷贝会发生的问题:

  • a原来的内存区域未释放,造成内存泄露。
  • a和b指向同一块区域,任何一方改变,会影响到另一方。
  • 当对象释放时,b会释放掉两次。

因此:当类中还有指针变量时,拷贝构造函数 和 赋值函数 就隐含了错误。此时需要自己定义。

具体解释网上有一位解释的非常好,找时间把地址贴过来。

不理解也没关系,只要记住一件事就好:必须要重写!

如果不想写拷贝构造函数和赋值函数,又不允许别人使用编译器生成的默认的函数,最简单的办法是将拷贝构造函数和赋值函数声明为私有函数

class A{    private:    A(const A& a);           // 私有拷贝构造函数    A& operate=(const A& a); // 私有赋值函数}

三、什么情况下使用

什么情况用到拷贝构造函数:
1)一个对象以值传递的方式传入函数体
2)一个对象以值传递的方式从函数返回
3)一个对象需要通过另一个对象进行初始化

class A {public:     A(A& x)        // 第一种形式};int Fun1(A x){   return x.a + x.b;}A Fun2(int a, int b){    A a(a, b);    return a;                                      }A c(10, 10);A d(c);              // 情况1) -> 调用拷贝构造函数int e = Fun1(c);     // 情况2) -> 调用拷贝构造函数A f = Fun2(11, 11);  // 情况3) -> 调用拷贝构造函数


P.S.

赋值函数需要处理自我赋值的问题,因为自我赋值会出现指针指向一个已经释放的内存。(详见最后一个链接的文章)

例子:

String::String(const String &other){    cout << "自定义拷贝构造函数" << endl;    int length = strlen(other.m_data);    m_data = new char[length + 1];    strcpy(m_data, other.m_data);}String & String::operator=(const String &other){    cout << "自定义赋值函数" << endl;     if (this == &other) //※    {        return *this;    }    else    {        delete [] m_data;        int length = strlen(other.m_data);        m_data = new char[length + 1];        strcpy(m_data, other.m_data);        return *this;    }}

四、文章推荐

几篇我认为对我帮助很大的好文章:

C++类中拷贝构造函数详解

C++中构造函数,拷贝构造函数和赋值函数的区别和实现

对于拷贝构造函数和赋值构造函数的理解

复制构造函数 与 赋值函数 的区别

C++赋值函数详解

阅读全文
0 0
原创粉丝点击