面试中的赋值运算符函数
来源:互联网 发布:网络教育和自考 编辑:程序博客网 时间:2024/05/23 00:17
(1)是否把返回值的类型声明为该类的引用,并在函数结束的时侯返回示例自身的引用(即*this).只有返回一个引用,才可以允许连续赋值。
(2)是否把参数的类型声明为常量引用。如果传入的参数不是引用而是实例,那么从形参到实参会调用一次构造函数。把参数声明为引用时可以避免这样无谓的消耗,能提高代码的效率。
(3)是否释放实例自身已有的内存。如果忘记释放,会导致内存的泄漏。
(4)是否判断传入的参数和当前的实例是不是同一个实例。如果是同一个,则不用进行赋值,直接返回。如果不进行判断时,会导致比较严重的问题就是,赋值的内容被删除了。
下面给出一个MyString类的实现:
#include<iostream>#include<string.h>#include<stdio.h>#include<stdlib.h>using namespace std;class MyString{public: MyString(char *pdata = NULL); MyString(const MyString& str); MyString& operator=(const MyString& str); ~MyString(void); void Print();private: char *m_pdata;};//构造函数MyString::MyString(char *pdata){ if(pdata == NULL){ m_pdata = new char[1]; m_pdata[0] = '\0'; }else{ int len = strlen(pdata); m_pdata = new char[len + 1]; strcpy(m_pdata,pdata); }}//拷贝构造函数MyString::MyString(const MyString& str){ int length = strlen(str.m_pdata); m_pdata = new char[length + 1]; strcpy(m_pdata,str.m_pdata);}//析构函数MyString::~MyString(){ delete []m_pdata;}//赋值运算MyString& MyString::operator = (const MyString& str){ if(this == &str){ return *this; } delete []m_pdata; m_pdata = NULL; m_pdata = new char[strlen(str.m_pdata) + 1]; strcpy(m_pdata,str.m_pdata); return *this;}void MyString::Print(){ printf("%s", m_pdata);}void Test1(){ printf("Test1 begins:\n"); char text[] = "Hello world"; MyString str1(text); MyString 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"; MyString 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"; MyString str1(text); MyString 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;}
我们先来看测试程序的执行结果:
根据测试的程序来看,赋值运算符函数基本没有什么问题了。
上述对于赋值运算符函数的实现只适用于初级的程序员,要想和别人不一样,我们就需要考虑下面的问题:
在前面的函数中,我们在分配内存之前先用delete释放了实例m_pdata的内存。如果此时内存不足导致new char抛出异常,m_pdata将是一个空指针,这样非常容易导致程序崩溃。也就是说一旦在赋值运算符内部抛出了一个异常,实例将不再保持原有的有效状态,这就违背了异常安全性的原则。
想要解决这个问题我们有两种办法:(1)一个简单的办法就是我们先用new 分配新内容再用delete释放已有的内容。这样只在分配i内容成功之后再释放原来的内容,当分配失败时,我们能确保原来的实例还存在。
(2)第二个更好的办法就是,先创建一个临时实例,再交换临时实例和原来的实例。
下面我们给出第二种办法的代码:
MyString& MyString::operator = (const MyString& str){ if(this != &str){ MyString strtemp(str); char *temp = strtemp.m_pdata; strtemp.m_pdata = m_pdata; m_pdata = temp; } return *this;}
局部的对象strtemp在函数执行完就要调用析构函数,利用析构函数释放了原来实例的内容。。。
- 面试中的赋值运算符函数
- 面试算法(一)赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- 赋值运算符函数
- C++ 中的赋值运算符重载和复制构造函数
- 赋值运算符重载函数
- 关于赋值运算符函数
- 赋值运算符重载函数
- 欧拉环、欧拉路径的判定和求法
- md5加密
- redis 主备哨兵模式
- 指针变量
- Android开发,美到超乎你想象的android开源交互动画和视觉效果,外部库
- 面试中的赋值运算符函数
- HTML页面头部信息
- Codeforces 639C Bear and Polynomials 【思维】
- c/c++浮点型数据转换成整型数据
- 网络驱动和网卡如何通信
- Codeforces Round #346 (Div. 2) D. Bicycle Race
- VS2005多语言支持
- 科学美国人:Raw Stone Age Meals Got Tenderizing Treatment
- fastjson 私有属性的坑