题中已给出CMyString的类定义,要求写赋值运算符函数。

 #include<iostream>
#include<cstring>
using namespace std; class CMyString
{
public:
CMyString(char* pdata = NULL);
CMyString(const CMyString& rstring);
CMyString& operator = (const CMyString& rstring);
void Show();
~CMyString();
private:
char* m_pdata;
}; CMyString::CMyString(char* pdata) //这里不能写char* pdata=NULL,一般如果函数声明和定义分开,则默认参数值在声明时 //写,定义时不用再写了
{
/*m_pdata = pdata; 不能直接这样赋值:如果这样赋值,则新创建的m_pdata和pdata指向同一内存,m_pdata的操作直接影
影响pdata*/ if(pdata == NULL)
{
m_pdata = NULL;
return;
}
int len = strlen(pdata);
m_pdata = new char[len + ];
strcpy(m_pdata,pdata);
}
CMyString::CMyString(const CMyString& rstring)
{
int len = strlen(rstring.m_pdata); //这里可以访问rstring的私有成员m_pdata
m_pdata = new char[len + ];
strcpy(m_pdata, rstring.m_pdata);
}
CMyString& CMyString::operator = (const CMyString& rstring)
{
if(this == &rstring)
return *this;
delete []m_pdata;
m_pdata = NULL;
m_pdata = new char[strlen(rstring.m_pdata)+];
strcpy(m_pdata,rstring.m_pdata);
}
CMyString::~CMyString()
{
delete []m_pdata;
}
void CMyString::Show()
{
cout<<m_pdata<<endl;
}
int main()
{
char* pa = "abcde";
char* pb = "qperwdfaafda";
CMyString a(pa);
a.Show();
CMyString b(pb);
b.Show();
CMyString c(b);
c.Show();
a = c;
a.Show();
return ;
}

关于拷贝构造函数:
定义:
拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。

调用情况:
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的
对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
例如:

String a(“hello”);
String b(“world”);
String c(a); //用已初始化过的a去初始化新对象c,调用拷贝构造函数
c = b; // 调用了赋值函数

拷贝构造函数中为什么可以调用参数的私有成员:
成员访问控制符public、private、protected都是基于类而言的,如果一个类标记了private访问权限,其意思是——这个类以外的其他类(友元类除外)无法访问被private修饰的本类成员,但是本类自身是不受成员访问符限制的。
class my;
my类中有一个private的成员num,其意思是——成员num对于my类以外的其他类(友元类除外)都不可见(或不可访问),但my类自己并不受限于访问权限。
拷贝构造函数的参数是同类的引用,属于“本类”的范围。

关于赋值函数:
赋值函数4步实现:
首先注意传入的参数是const CMyString& rstring,常引用:
为什么是引用:如果参数不是引用而是实例,则从形参到实参相当于用已有对象去初始化一个新对象,要调用复制构造函数,造成不必要开销。
为什么是const:因为赋值函数内不会改变传入参数的状态,因此应该为传入的参数加上const。
(1)检查自赋值:判断传入的参数和当前实例(*this)是否为同一个,如果是同一个则直接返回。没有这一步的后果:一旦传入的是自身,则在第二步会delete自己,一旦释放自己的内存,参数也被释放了(自杀后不能复制自己),因此找不到需要复制的内容了。
(2)用delete 释放原有的内存资源。如果现在不释放,以后就没机会了,将造成内存泄露。
(3)分配新的内存资源,并复制字符串。
(4)返回本对象的引用:目的是为了实现stra = strb = strc这样的连续赋值,如果是void则不能实现连续赋值。另外返回引用而不是实例也是为了避免调用拷贝构造函数。

参考:

http://www.cnblogs.com/BlueTzar/articles/1223313.html  C++拷贝构造函数(深拷贝,浅拷贝)

http://blog.chinaunix.net/uid-25808509-id-354211.html   C++ 拷贝构造函数 赋值构造函数

《剑指offer》面试题1:为类CMyString添加赋值运算符函数——C++拷贝构造函数与赋值函数的更多相关文章

  1. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  2. 剑指offer面试题3 二维数组中的查找(c)

    剑指offer面试题三:

  3. 剑指Offer——笔试题+知识点总结

    剑指Offer--笔试题+知识点总结 情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观, ...

  4. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  5. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解

    剑指offer  面试题23:从上往下打印二叉树 参与人数:4853  时间限制:1秒  空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...

  6. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  7. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

  8. C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解

    剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...

  9. C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解

    剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...

随机推荐

  1. jsp 下拉框首字母定位可检索

    实现效果如图: 页面部分: (1)js中: (2)body中: JAVA代码部分: 控制器Controller中 写一个页面js中调用的方法: 引入jar包:

  2. nginx的源代码分析--间接回调机制的使用和类比

    nginx使用了间接回调机制.结合upstream机制的使用来说明一下,首先明白几个事实: 1)事实上ngxin和下游client的连接使用的是ngx_http_connection_t,每一个连接相 ...

  3. Ajax技术实现页面无刷新跳转

    Ajax实现无刷新显示新的页面 <!DOCTYPE html> <html> <head> <script src="/jquery/jquery- ...

  4. CXF实战之自己定义拦截器(五)

    CXF已经内置了一些拦截器,这些拦截器大部分默认加入到拦截器链中,有些拦截器也能够手动加入,如手动加入CXF提供的日志拦截器.也能够自己定义拦截器.CXF中实现自己定义拦截器非常easy.仅仅要继承A ...

  5. xcode升级到6.0以后遇到的警告错误解决方法

    Xcode 升级后,常常遇到的遇到的警告.错误,解决方法 从sdk3.2.5升级到sdk 7.1中间废弃了很多的方法,还有一些逻辑关系更加严谨了.1,警告:“xoxoxoxo”  is depreca ...

  6. 无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护

    golang/goroutine 和 swoole/coroutine 协程性能测试对比 - Go语言中文网 - Golang中文社区 https://studygolang.com/articles ...

  7. Node 文件上传,ZIP

    上传文件: 很多人会使用第三包进行文件的上传,例如formidable. 我也研究过,可是与Express3.x框架一起使用时,发现上传的文件总是找不到.结果原因是下面这句导致: app.use(ex ...

  8. BZOJ3231: [Sdoi2008]递归数列

    BZOJ3231: [Sdoi2008]递归数列 Description 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + ...

  9. Linux就该这么学--命令集合4(文件目录管理命令)

    1.touch命令用于创建空白文件与修改文件时间:(touch [选项] [文件]) 对于在Linux中的文件有三种时间: 更改时间(mtime):内容修改时间(不包括权限的) 更改权限(ctime) ...

  10. CoreGraphics(转)

    2.CoreGraphics 上面我们讲过,UIBezierPath是CoreGraphics的封装,使用它可以完成大部分的绘图操作,不过更底层的CoreGraphics更加强大. CoreGraph ...