剑指offer之赋值操作符

题目描述:

个人觉得,类中四少(构造函数、拷贝构造函数、赋值操作符、析构函数)都有一些注意点,于是都实现了下,注意点均有标注(注意下^_^)

#include<iostream>
#include<vld.h>
using namespace std;

class CMyString{
public:

	/*
		赋值语句:(四部曲)
			1:检查自赋值
			2:释放原有空间
			3:开辟新空间并赋值
			4:return *this
	*/

	CMyString& operator=(const CMyString &str){
		if (this != &str){
			delete[] m_pData;//1
			m_pData = NULL;
			int len = strlen(str.m_pData) + 1;
			m_pData = new char[len];//2
			strcpy_s(m_pData, len, str.m_pData);//3
		}
		return *this;//4
	}
	explicit CMyString(const char *pData = NULL){//explicit防止类型的隐式转换:如CMyString str = "hello";
		if (pData == NULL){//为空的情况要单独考虑(strlen(NULL)会导致程序崩溃)
			m_pData = new char[1]; //即使开辟一个空间也使用new[]---->与析构函数delete[]相对应
			m_pData[0] = '\0';
		}
		else{
			int len = strlen(pData) + 1;
			m_pData = new char[len];
			strcpy_s(m_pData, len, pData);
		}
	}

	CMyString(const CMyString &str){
		int len = strlen(str.m_pData)+1;
		m_pData = new char[len];
		strcpy_s(m_pData, len, str.m_pData);
	}

	virtual ~CMyString(void){//析构函数一般声明为虚函数(继承时保证析构函数的调用顺序,防止内存泄露)
		delete[] m_pData;
		m_pData = NULL;
	}
private:
	char *m_pData;
};

赋值操作符函数:

版本一:

//版本一:先释放原有空间->开辟新空间 如new开辟空间失败,那么原有的空间(内容)也不复存在(未考虑异常安全)
	CMyString& operator=(const CMyString &str){
		if (this != &str){
			delete[] m_pData;//1
			m_pData = NULL;
			int len = strlen(str.m_pData) + 1;
			m_pData = new char[len];//2
			strcpy_s(m_pData, len, str.m_pData);//3
		}
		return *this;//4
	}

版本二:

//版本二:保证空间开辟失败,原有的内容依旧存在
CMyString& operator=(const CMyString &str){
	if (this != &str){
		int len = strlen(str.m_pData) + 1;
		char *tmp = new char[len];//new 失败时会发出异常,不会执行到下一步delete[] m_pData
		delete[] m_pData;         //若执行到下一步delete[] m_pData,说明空间开辟成功
		m_pData = tmp;
		strcpy_s(m_pData, len, str.m_pData);
	}
	return *this;
}

版本三:(推荐)

//版本三:利用局部临时对象的生存期
CMyString& operator=(const CMyString &str){
	if (this != &str){
		CMyString tmp(str.m_pData);
		swap(m_pData, tmp.m_pData);//交换各自m_pData所指的空间,临时对象出了作用域if,调用析构函数释放m_pData
								   //所指向的空间
	}
	return *this;
}

测试用例:

int main()
{
	CMyString str("hello");
	str = str;//自赋值( if(this != &str) )

	CMyString str1("xxxxxx");//一般赋值
	str1 = str;

	CMyString str3;
	str3 = str = str1;//连续赋值(返回CMystring &的重要性)
	system("pause");
	return 0;
}

注:

1、#include<vld.h> 是一款用来检测内存泄露的工具(vld)-->因为operator=中涉及众多内存释放开辟

(养成良好编程习惯)点击打开链接(vld使用教程)

2、开发平台:VS2013(所以使用了strcpy_s函数)

时间: 2024-10-07 00:29:21

剑指offer之赋值操作符的相关文章

最大子列和问题(剑指offer和PAT)

01-复杂度1 最大子列和问题   (20分) 给定KK个整数组成的序列{ N_1N?1??, N_2N?2??, ..., N_KN?K?? },“连续子列”被定义为{ N_iN?i??, N_{i+1}N?i+1??, ..., N_jN?j?? },其中 1 \le i \le j \le K1≤i≤j≤K.“最大子列和”则被定义为所有连续子列元素的和中最大者.例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20.现要求你编

剑指offer (2) c++实现singleton模式

转自:http://www.jellythink.com/archives/82 问题描述 现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能:在实际开发过程中,会专门有一个日志模块,负责写日志,由于在系统的任何地方,我们都有可能要调用日志模块中的函数,进行写日志.那么,如何构造一个日志模块的实例呢?难道,每次new一个日志模块实例,写完日志,再delete,不要告诉我你是这么干的.在C++中,可以构造一个日志模块的全局变量,那么在任何地方就都可以用了,是的,不错.但是

剑指offer (5) 链表插入删除

我们在操作链表的时候,必须注意以下事项: 1. 链表指针为NULL的情况 2. 插入删除涉及到 链表第一个节点时,需要修改 链表的第一个节点: a. 因为 c语言都是传值的,如果需要修改一个变量,就必须通过 指向该变量的指针(即该变量的地址) 例如:例如 修改 int a,则输入参数必须是 int* a, 修改a 则是: *a = b; (b为int) 我们需要修改一个指针时,就必须通过 该指针的地址,也就是 指向该指针的指针,即二级指针 例如  修改 int* a, 则输入参数必须是 int*

剑指offer(1):数组

1 写作计划 最近在看<剑指offer>,发现自己有很多的数据结构与算法的基础知识要复习,<好书一起读(131):让写作更好>中提到用写作倒逼阅读,我很是赞同.所以,计划以<剑指offer>为中心,以记录复习心得目的,写一系列数据结构与算法的文章. 文章结构 文章从概念介绍切入,接着介绍相关的语言细节(以C语言和Python为主),最后以<剑指offer>中的编程题做结. 2 什么是数组 一提到数组,我第一时间经典的C语言实现和与之对应的一片定长连续的内存空

【剑指offer】删除在另一个字符串中出现的字符

转载请注明出处:http://blog.csdn.net/ns_code/article/details/27110873 剑指offer上的字符串相关题目. 题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符.例如,输入"They are students."和"aeiou",则删除之后的第一个字符串变成"Thy r stdnts.". 这里主要要分析两个方面: 1.如何判断那些字符是需要删除的字符.同很多字符串问题一样,可以开辟

【剑指offer】删除字符也出现在一个字符串

转载请注明出处:http://blog.csdn.net/ns_code/article/details/27110873 剑指offer上的字符串相关题目. 题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符.比如.输入"They are students."和"aeiou",则删除之后的第一个字符串变成"Thy r stdnts.". 这里主要要分析两个方面: 1.怎样推断那些字符是须要删除的字符. 同非常多字符串问题一样.能够

剑指offer题目系列三(链表相关题目)

本篇延续上一篇剑指offer题目系列二,介绍<剑指offer>第二版中的四个题目:O(1)时间内删除链表结点.链表中倒数第k个结点.反转链表.合并两个排序的链表.同样,这些题目并非严格按照书中的顺序展示的,而是按自己学习的顺序,每个题目包含了分析和代码. 9.O(1)时间内删除链表结点 题目: 在O(1)时间内删除链表结点.给定单链表的头指针和一个结点指针,定义一个方法在O(1)时间内删除该结点. 单链表的定义如下: 解答: 单向链表删除一个结点,最直观的想法是从链表的头结点开始顺序遍历查找要

《剑指offer》全部题目-含Java实现

陆续刷了好久,算是刷完了<剑指offer>,以下全部AC代码,不一定性能最优,如有错误或更好解答,请留言区指出,大家共同交流,谢谢~ 1.二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. public class Solution { public boolean Find(int target, int [][] array) { if(array == n

结合《剑指offer(第二版)》面试题51来谈谈归并排序

一.题目大意 给定一个数组A,对于数组A中的两个数字,如果排在前面的一个数字大于(必须大于,等于不算)后面的数字,则这两个数字组成一个逆序对.要求输出数组A中的逆序对的总数.例如,对于数组{7,5,6,4},一共存在5个逆序对,分别是(7,5).(7,6).(7,4).(5,4).(6,4). 注:根据题意可知,必须根据原数组中元素的相对顺序来统计,给定的数组时怎样,那就按照怎样的顺序. 二.思路分析 方法1:暴力破解.双重循环来判断出所有的逆序对数,时间复杂度为O(N^2),空间复杂度为O(1