zoukankan      html  css  js  c++  java
  • 剑指offer-面试题1:赋值运算符函数

    题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数

     1 class CMyString
     2 {
     3 public:
     4     CMyString(char *pData=NULL);
     5     CMyString(const CMyString & str);
     6     ~CMyString(void);
     7 
     8 private:
     9     char * m_pData;
    10 };

    首先在解答这道题目之前,先要作一些说明:

    1.任何类都是默认的重载赋值操作符。

    2.类一旦被声明并且编译后就会为该类的实例分配内存。

    3.如果类的成员变量没有在堆(动态分配)中分配内存,那么无需重载赋值操作符也可。因为这样的赋值只

    是为每个成员变量赋值而已。

    比如:对象A有成员变量int a1

    1 A a;
    2 a.a1=1;
    3 A b;
    4 b.a1=2; 
    5 a=b;

    当执行到a=b;这一步的时候其实即使我们没有重载赋值操作符,也会调用类A的对象a的默认赋值函数

    1 void A::operate = (A b)
    2 { 
    3     this.a1=b.b1;
    6 }

    至此,对象a中的a1成功赋值为b1即2,没有问题的。

     

    接下来我们要考虑另外一种情况

    假如类A中有一个指针成员变量int *ptr;该ptr在构造函数中new了一块内存。

    那么我们重新考虑类A的两个对象a,b

    对象a,b分别有一个指针ptr,并且该指针在构造函数中分别new了一块内存我们分别以mema和memb表示。

    在a的ptr中new的内存mema中的值我们设为1,在b的ptr中new的内存memb中的值我们设为2.

    1 A a;/在构造函数new ptr(mema)
    3 A b;/在构造函数new ptr(memb)
    5 a=b;

    当我们执行到a=b这一步的时候,我们如果没有重载赋值操作符。那么

    1 void A::operate = (A b)
    2 {
    3      this.ptr=b.ptr;5 }

    乍看好像也没什么错,是的 this.ptr=b.ptr这句是将对象b.ptr的所指向的内推地址memb赋值给了a.ptr所

    指向的对象。好了问题来了,那么a.ptr所指向的那块内推是分配在堆中的也就所如果我们没有主动释放它

    是不会自动释放的。然而a.ptr已经指向了memb,这样很明显对象a出现了内存泄露。当然问题还不止于

    此,现在a.ptr和b.ptr都同时指向了memb.那么如果当对象a或者b结束后必然会释放掉memb,比如说a先结束

    释放memb,那么b.ptr是不是就成了野指针了呢,如果b先结束,那么a.ptr便成为了野指针,同时对象a还出现了内存泄露.

    那么你会问为什么之前直接赋值就可以而这里直接赋值就不行呢,这就涉及一个内存管理的问题,分配在堆的

    内存是需要我们用户自己释放的,而分配在栈的内存是由程序自己管理,程序结束后会自动释放。

     

    现在明白重载赋值操作符的场景了吧,

    那么还有几点需要说明:

    1.赋值操作符重载通常形参我们是引用,引用可以减少直接传值带来的构造开销.

    2.赋值操作符重载通常形参是常量,这是为了防止在赋值过程中操作符右值被修改。

    3.如果为了连续赋值应该把返回值类型声明为该类型的引用,否则函数的返回值为void,不能连续赋值。

    4.当然为我们还应该考虑传入的对象是否和被赋值对象是否相等。

     

    综合以上因素,这道题结果如下:

     1 CMyString& CMyString::operator = (const CMyString& str)
     2 {
     3     if(this==&str)
     4         return *this;
     5 
     6     delete []m_pData;
     7     m_pData=NULL;
     8 
     9     m_pData=new char[strlen(str.m_pData)+1];
    10 
    11     strcpy(m_pData,str.m_pData);
    12 
    13     return *this;
    14 }
  • 相关阅读:
    jQuery常用方法总结
    如何让div显示在最上层(页面含Flash)
    Flex分页控件
    C#利用SharpZipLib解压或压缩文件夹实例操作
    3D 穿梭效果?使用 UWP 也能搞定
    [WPF] 制作一个彩虹按钮
    [WPF] 仅用 Rectangle 实现圆柱形进度条
    [WPF] 玩玩彩虹文字及动画
    Skipping Windows Azure Startup Tasks When Running in the Emulator
    [转] Asp.net mvc 3 beta 新特性介绍
  • 原文地址:https://www.cnblogs.com/vpoet/p/4662589.html
Copyright © 2011-2022 走看看