《剑指offer》面试题1:为类CMyString添加赋值运算符函数——C++拷贝构造函数与赋值函数
题中已给出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++拷贝构造函数与赋值函数的更多相关文章
- 剑指Offer:面试题15——链表中倒数第k个结点(java实现)
问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...
- 剑指offer面试题3 二维数组中的查找(c)
剑指offer面试题三:
- 剑指Offer——笔试题+知识点总结
剑指Offer--笔试题+知识点总结 情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观, ...
- C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告
剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...
- C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解
剑指offer 面试题23:从上往下打印二叉树 参与人数:4853 时间限制:1秒 空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...
- C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解
剑指offer 面试题39:判断平衡二叉树 提交网址: http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...
- Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)
剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...
- C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解
剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...
- C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解
剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...
随机推荐
- Spring Boot 测试时的日志级别
1.概览 该教程中,我将向你展示:如何在测试时设置spring boot 日志级别.虽然我们可以在测试通过时忽略日志,但是如果需要诊断失败的测试,选择正确的日志级别是非常重要的. 2.日志级别的重要性 ...
- SSH实现在WIN7系统下访问虚拟机中的Linux系统
使用的是centos6.4进行练习的,安装的是vmware8虚拟机.以下是总结的一些步骤: 一.确保vmware使用NAT的连接方式,如做地址.端口映射 首先查看vmware的中网络连接的一些方式:E ...
- crazyflie2.0 RCC时钟知识
因为眼下手里仅仅有16MHZ的2520封装的贴片晶振,8MHZ这样的封装做不到这么小,所以就先用16MHZ,这样我们就须要改动程序相关的RCC时钟: 1,stm32f4xx.h #define HSE ...
- less 一种 动态 样式 语言
LESS « 一种动态样式语言 http://www.bootcss.com/p/lesscss/ 一种 动态 样式 语言. LESS 将 CSS 赋予了动态语言的特性,如 变量, 继承,运算, 函数 ...
- Hive与impala的对比测试实验
前面几篇随笔记录了我安装环境的一些笔记,环境ok以后,自然要看看impala到底性能如何,拿他来hive做做对比: 前面hive章节中,已经建立了一张名叫chengyeliang的table,该表的结 ...
- mysql错误指令:Failed to open file "file_name" error 2/error 22
网上说Linux下可能会有此问题,及导入sql文件时出现如标题所示的错误.而我用的是windows系统,也出现了同样的问题. source filename | \. filename 执行这条语 ...
- AmIBeingDebugged 函数方法的定义实现
#include <assert.h> #include <stdbool.h> #include <sys/types.h> #include <unist ...
- 简述arp协议的工作原理
在每台安装有TCP/IP协议的电脑里都有一个ARP缓存表,表里的IP地址与MAC地址是一一对应的,如: 我们以主机A(192.168.1.5)向主机B(192.168.1.1)发送数据为例.当发送数据 ...
- Vue实例和方法
github地址:https://github.com/manlili/vue_learn里面的lesson03 一 实例 每个 Vue 实例都会代理其 data 对象里所有的属性,改变data,vu ...
- Nginx安装教程(Centos6.8)
1.安装gcc gcc-c++(如新环境,未安装请先安装 yum install -y gcc gcc-c++ 2.安装wget yum -y install wget 3.安装PCRE库 cd /h ...