剑指offer (01):赋值运算符函数 (C++ 实现)
1 题目
如下为类型 CMystring
的声明,请为该类型添加赋值运算符函数。
class CMyString
{
public:CMyString(char* pData = nullptr);CMyString(const CMyString& str);~CMyString(void);
private:char* m_pData;
};
2 题解
这道题就是一道重载赋值运算符为成员函数的题。需要考虑以下几点:
- 是否把返回值的类型声明为该类型的引用(
CMystring& ...
),并在函数结束后返回实例的引用(*this
)。只有返回一个,才可以连续赋值。否则,如果返回值是void,将不能连续赋值。 - 是否把传入的参数的类型声明为常量引用(
const CMystring &str
)。如果传入的不是引用而是实例,那么从形参到实参会调用一次复制构造函数。把参数声明为引用可以避免这样的无谓消耗,提高效率。同时,我们在函数内不会修改传入的实例的状态,因此应该加上const
关键字。 - 是否释放实例自身已有的内存。若未在分配空间前释放自身已有的空间,将会造成内存泄漏。
- 判断传入的参数和当前的实例(
*this
)是不是同一个实例。如果是,则不赋值。如果不判断,在释放自身内存时,也会删除原有的内存,就再也找不到赋值的内容。
2.1 经典解法,初级程序员
CMyString& CMyString::operator=(const CMystring& str)
{// 判断是否为自身if(this == &str)return *this;// 赋值前先删除原有内容delete []m_pData;m_pData = nullptr;m_pData = new char[strlen(str.m_pData) + 1];strcpy(m_pData, str.m_pData);return *this;
}
注意:
这样做乍一看很不错,但是在分配内存之前先用 delete
释放了实例 m_pData
的内存。此时,若内存不足导致new char
抛出异常,则 m_pData
就是一个空指针,容易导致程序崩溃,也丢失了我们自身原来的内容。
要想解决这个问题,有两个办法:
- 先
new
分配新内容,再delete
释放已有内容。这样及时分配内存失败,亦可以保留原先的实例不会被修改。 - 更好的办法是用赋值的实例创建一个临时实例,再交换临时实例和原来的实例。
2.2 高级解法,考虑异常安全性
CMyString & CMyString::operator=(const CMyString & str)
{if (this != &str){// 创建临时实例,相当于把要赋值的内容也传入了临时变量!CMyString strTemp(str); // 然后交换指向,新换旧,旧换新, 完成赋值。char* pTemp = strTemp.m_pData;strTemp.m_pData = m_pData;m_pData = pTemp;}return *this;
}
由于strTemp
是一个局部变量,当程序运行到if
的外面时,也就出了改变量的作用域,就会自动调用 strTemp
的析构函数, 释放掉原有的内存。
同时我们在 CMystring
的构造函数里用 new
分配内存。若内存不足抛出诸如 bad_alloc 异常,但我们还没有修改原来实例的状态,这也就保证了异常安全性。
3 完整代码
#define _CRT_SECURE_NO_WARNINGS // 否则报不安全,VS2015#include <cstdio>
#include <cstring>class CMyString
{
public:CMyString(char* pData = nullptr);CMyString(const CMyString& str);~CMyString(void); CMyString& operator = (const CMyString& str); // 重载运算符 = void Print(); private:char* m_pData;
};CMyString::CMyString(char * pData)
{if (pData == nullptr) // 判断是否为空指针{m_pData = new char[1];m_pData[0] = '\0';}else{int length = strlen(pData);m_pData = new char[length + 1];strcpy(m_pData, pData);}
}CMyString::CMyString(const CMyString & str)
{int length = strlen(str.m_pData);m_pData = new char[length + 1];strcpy(m_pData, str.m_pData);
}CMyString::~CMyString()
{delete[] m_pData;
}/*
// 初级做法,未考虑内存不足时的异常安全性
CMyString& CMyString::operator=(const CMystring& str)
{// 判断是否为自身if(this == &str)return *this;// 赋值前先删除原有内容delete []m_pData;m_pData = nullptr;m_pData = new char[strlen(str.m_pData) + 1];strcpy(m_pData, str.m_pData);return *this;
}
*/// 高级做法 A = B
CMyString & CMyString::operator=(const CMyString & str)
{if (this != &str){// 创建临时实例,相当于把要赋值的内容也传入了临时变量!CMyString strTemp(str); // 然后交换指向,新换旧,旧换新, 完成赋值。char* pTemp = strTemp.m_pData;strTemp.m_pData = m_pData;m_pData = pTemp;}return *this;
}void CMyString::Print()
{printf("%s", m_pData);
}// ============================= 测试用例 =================================
// 正常赋值
void Test1()
{printf("Test1 begins:\n");char* text = "Hello world";CMyString str1(text);CMyString str2;str2 = str1;printf("The expected result is: %s.\n", text);printf("The actual result is: ");str2.Print();printf(".\n");
}// 赋值给自己
void Test2()
{printf("Test2 begins:\n");char* text = "Hello world";CMyString str1(text);str1 = str1;printf("The expected result is: %s.\n", text);printf("The actual result is: ");str1.Print();printf(".\n");
}// 连续赋值
void Test3()
{printf("Test3 begins:\n");char* text = "Hello world";CMyString str1(text);CMyString str2, str3;str3 = str2 = str1;printf("The expected result is: %s.\n", text);printf("The actual result is: ");str2.Print();printf(".\n");printf("The expected result is: %s.\n", text);printf("The actual result is: ");str3.Print();printf(".\n");
}int main(int argc, char* argv[])
{Test1();Test2();Test3();return 0;
}
剑指offer (01):赋值运算符函数 (C++ 实现)相关推荐
- 剑指Offer #01 二维数组中的查找(Java描述)
题目来源:牛客网-剑指Offer专题 题目地址:二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一 ...
- 《剑指offer》Partition函数及其Partition函数周边
Partion函数最早出现于快速排序算法,但其代表的分治思想,在<剑指offer>这本书中求数组中位数(面试题39,数组中出现次数超过一半的数字)中也有所涉及,将其汇总在一起,称之为P ...
- python剑指offer 包含min函数的栈
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). # -*- coding:utf-8 -*- class Solution:def _ ...
- 剑指Offer 包含min函数的栈
时间限制:1秒 空间限制:32768K 热度指数:158697 本题知识点: 栈 算法知识视频讲解 题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 给出代码: cla ...
- 剑指offer 包含min函数的栈
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 先介绍一下java.util.Stack.peek()方法实例: 下面的例子显示java.util.Stack.pee ...
- 剑指offer——01二维数组中的查找.
class Solution {public:bool Find(int target, vector<vector<int> > array) {int m =array.s ...
- 剑指offer.01 数组中重复的数(0504刷题自用)
代码 class Solution {public:int findRepeatNumber(vector<int>& nums) {unordered_map <int,i ...
- 《剑指offer》写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。...
弱菜刷题还是刷中文题好了,没必要和英文过不去,现在的重点是基本代码能力的恢复. [题目] 剑指offer 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. [思路] 直觉 ...
- 赋值运算符函数__from 剑指Offer
前段时间忙于项目,难得偷得几日闲,为即将到来的就业季做准备.在面试时,应聘者要注意多和考官交流,只有具备良好的沟通能力,才能充分了解面试官的需求,从而有针对性地选择算法解决问题. 题目来源于<剑 ...
最新文章
- 2020阿里全球数学大赛:3万名高手、4道题、2天2夜未交卷,73人天团,正式出道!
- oracle 默认表空间 10g,Oracle10g 表空间管理
- 认知AI的兴起:2025年AI将会发生质的飞跃
- 【死磕Java并发】-----Java内存模型之happens-before
- jqgrid的动态下拉框实现,并解决不能获取值的问题
- WebBrowser1.Navigate重复载入同一页面时载入的是旧页面
- sublime text 3 中的php代码语法检测
- XML配置文件中的Spring配置文件
- android:图片裁剪
- 【Tyvj】1473校门外的树3 线段树/树状数组 区间修改+单点访问
- 宅男福利!20行Python代码,一网打尽B站小姐姐的直播信号源!
- 黑客入侵效果网页html,满屏绿字滑下效果
- 计算机配置里面没有网络选项,win7网络共享中心里面的更改适配器设置里面没有无线网络连接...-win7适配器没有无线网络连接,win7网络适配器未...
- table 手机 滑动_移动端touch事件滚动
- 【懒懒的Python学习笔记九】
- WPA3也不安全啦?WPA3-R3 H2E了解一下
- 基于android的手机掌上购物
- 解决:FTP隔离用户ftp将数据发送到服务器之前不加密或编码,要保护密码和数据数据,请用WEB文件夹(WenDAV)
- Python find()方法
- 计算机科学与技术在国内外的形势,计算机科学与技术就业形势分析