zoukankan      html  css  js  c++  java
  • 从零开始学C++之构造函数与析构函数(三):深拷贝与浅拷贝、空类

    一、深拷贝与浅拷贝

    说得简单点,假设一个类有指针成员,如果在拷贝的时候顺带连指针指向的内存也分配了,就称为深拷贝;如果只是分配指针本身的内存,那就是浅拷贝。浅拷贝造成的问题是有两个指针指向同块内存,delete 其中一个指针,那么剩下的指针将成为野指针。编译器合成的默认拷贝构造函数和赋值运算符是浅拷贝的,如果只是普通成员的赋值,浅拷贝也是可以的。

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    #ifndef _STRING_H_
    #define _STRING_H_

    class String
    {
    public:
        String( char *str =  "");
        ~String();
        String( const String &other);
        String & operator=( const String &other);



         void Display();

    private:
         char *AllocAndCpy( char *str);

         char *str_;
    };

    #endif  // _STRING_H_
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #include  "String.h"
    //#include <string.h>
    #include <cstring>
    #include <iostream>
    using  namespace std;

    String::String( char *str /* = */)
    {
        str_ = AllocAndCpy(str);
    }

    String::~String()
    {
         delete[] str_;
    }

    String::String( const String &other)
    {
        str_ = AllocAndCpy(other.str_);
    }

    String &String:: operator =( const String &other)
    {
         if ( this == &other)
             return * this;

         delete[] str_;
        str_ = AllocAndCpy(other.str_);
         return * this;
    }

    char *String::AllocAndCpy( char *str)
    {
         int len = strlen(str) +  1;
         char *tmp =  new  char[len];
        memset(tmp,  0, len);
        strcpy(tmp, str);
         return tmp;
    }

    void String::Display()
    {
        cout << str_ << endl;
    }
     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include  "String.h"

    int main( void)
    {
        String s1( "AAA");
        s1.Display();
        String s2 = s1;      // 调用拷贝构造函数
         // 系统提供的默认拷贝构造函数实施的是浅拷贝 s2.str_ = s1.str_

        String s3;
        s3.Display();
        s3 = s2;             // 调用等号运算符
         // 系统提供的默认等号运算符实施的是浅拷贝 s3.str_ = s2.str_;
         // s3.operator=(s2);
    s3.Display();
         // 要让对象是独一无二的,我们要禁止拷贝
         // 方法是将拷贝构造函数与=运算符声明为私有,并且不提供它们的实现
         return  0;
    }

    上面程序中String 类有一个char* str_ 成员,故实现了深拷贝,这样不会造成内存被释放两次的错误,或者修改指针指向的内存会影响另一个对象的错误。此外,如果我们想让对象是独一无二的,需要禁止拷贝,只需要将拷贝构造函数和等号运算符声明为私有,并且不提供它们的实现。


    二、空类

    空类默认产生的成员:

    class Empty {};
    Empty(); // 默认构造函数
    Empty( const Empty& );// 默认拷贝构造函数
    ~Empty(); // 默认析构函数
    Empty& operator=( const Empty& );  // 默认赋值运算符
    Empty* operator&();              // 取址运算符
    const Empty* operator&() const;   // 取址运算符 const

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    #include <iostream>
    using  namespace std;

    class Empty
    {
    public:
        Empty * operator&()
        {
            cout <<  "AAAA" << endl;
             return  this;
        }

         const Empty * operator&()  const
        {
            cout <<  "BBBB" << endl;
             return  this;
        }
    };

    int main( void)
    {
        Empty e;
        Empty *p = &e;       // 等价于e.operator&();

         const Empty e2;
         const Empty *p2 = &e2;

        cout <<  sizeof(Empty) << endl;

         return  0;
    }


    单步调试一下,可以看到分别调用了两个取地址运算符函数,而且空类的大小为1个字节。


  • 相关阅读:
    jquery正则表达式验证:正整数(限制长度)
    H5页面快速搭建之高级字体应用实践
    如何用Python写一个贪吃蛇AI
    HashMap多线程并发问题分析
    为RecyclerView打造通用Adapter 让RecyclerView更加好用
    学好Mac常用命令,助力iOS开发
    使用 Realm 和 Swift 创建 ToDo 应用
    看Facebook是如何优化React Native性能
    利用github搭建个人maven仓库
    Objective-C Runtime之着魔的UIAlertView
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3159704.html
Copyright © 2011-2022 走看看