zoukankan      html  css  js  c++  java
  • C++11 指针成员与拷贝构造(浅拷贝与深拷贝)

    【1】浅拷贝

    一直以来,设计一个类,个人认为,最能体现水平的地方在于:类中含有指针成员变量。

    如下一个典型的浅拷贝示例:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class HasPtrMem
     5 { 
     6 public:
     7     HasPtrMem() : d(new int(0))
     8     {} 
     9     ~HasPtrMem() 
    10     { 
    11         delete d;
    12         d = nullptr;
    13     }
    14     
    15     int* d;
    16 }; 
    17 
    18 int main()
    19 { 
    20     HasPtrMem a; 
    21     HasPtrMem b(a); 
    22     
    23     cout << *a.d << endl; // 0
    24     cout << *b.d << endl; // 0
    25 } // 异常析构

    定义了一个含有指针成员变量d的类型HasPtrMem。

    该成员d在构造时会接受一个new操作分配堆内存返回的指针,而在析构的时候则会被delete操作用于释放分配的堆内存。

    在main函数中,声明了HasPtrMem类型的对象a,又使用a初始化了对象b。按照C++的语法,这会调用HasPtrMem的拷贝构造函数。

    而这里的拷贝构造函数由编译器隐式生成,其作用是执行类似于memcpy的按位拷贝。

    这样的构造方式有一个问题,就是a.d和b.d都指向了同一块堆内存。

    因此在main作用域结束的时候,对象b和对象a的析构函数会分别依次被调用。

    当其中之一完成析构之后(比如对象b先析构,b.d先被delete),那么a.d就成了一个“悬挂指针”(dangling pointer),因为其不再指向有效的内存了。

    那么在该悬挂指针上释放内存就会造成严重的错误。

    【2】深拷贝

    通常情况下,在类中未声明构造函数的情况下,C++也会为类生成一个“浅拷贝”(shollow copy)的构造函数。

    而最佳的解决方案是用户自定义拷贝构造函数来实现“深拷贝”(deep copy),修正上例为深拷贝的结果:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class HasPtrMem
     5 { 
     6 public:
     7     HasPtrMem() : d(new int(0))
     8     {}
     9     HasPtrMem(const HasPtrMem& h) : d(new int(*h.d)) { } // 拷贝构造函数,从堆中分配内存,并用*h.d初始化
    10     ~HasPtrMem() 
    11     { 
    12         delete d;
    13         d = nullptr;
    14     }
    15     
    16     int* d;
    17 }; 
    18 
    19 int main()
    20 { 
    21     HasPtrMem a; 
    22     HasPtrMem b(a); 
    23     
    24     cout << *a.d << endl; // 0
    25     cout << *b.d << endl; // 0
    26 } // 正常析构

    为类HasPtrMem添加了一个拷贝构造函数。

    拷贝构造函数从堆中分配新内存,将该分配来的内存的指针交还给d,又使用*(h.d)对*d进行了初始化。

    通过这样的方法,就避免了悬挂指针的困扰。

    good good study, day day up.

    顺序 选择 循环 总结

  • 相关阅读:
    D. Constructing the Array
    B. Navigation System
    B. Dreamoon Likes Sequences
    A. Linova and Kingdom
    G. Special Permutation
    B. Xenia and Colorful Gems
    Firetrucks Are Red
    java getInstance()的使用
    java 静态代理和动态代理
    java 类加载机制和反射机制
  • 原文地址:https://www.cnblogs.com/Braveliu/p/12233571.html
Copyright © 2011-2022 走看看