C++重载赋值操作符
1、C++中重载赋值操作函数应该返回什么?
类重载赋值操作符一般都是作为成员函数而存在的,那函数应该返回什么类型呢?参考内置类型的赋值操作,例如
int x,y,z;
x=y=z=15;
赋值行为相当于x=(y=(z=15)),也就是赋值操作应该返回左操作数的引用,因此,为了和内置类型兼容,类中重载赋值操作符应该返回左操作数的引用,即*this,如下类A的重载赋值操作函数的声明,
class A{};
A& A::operator=(const A&);
2、确保重载赋值操作具有良好的行为
对于赋值操作,首先应该想到的是怎么处理自我赋值,当类包含指针类型的数据时尤为重要,如下所示
class MyString{
public:
...
MyString(char *p=NULL);
MyString& operator=(const MyString&);
private:
char *str;
};
MyString a("hello");
MyString b("world");
a=a;
我们知道,进行赋值时,首先要释放左操作数的资源,然后再根据右操作数对左操作数进行赋值,赋值操作函数如下所示
MyString& MyString::operator=(const MyString& rhs){
delete [] str;
str=new char[strlen(rhs.str)+1];
strcpy(str,rhs.str);
return *this;
}
当运行a=a时,会产生意向不到的后果,我们在函数中先释放了左操作数的资源,然后访问右操作数的资源,然后当自我赋值发生时,this==&rhs,也就是说我们先释放了资源,然后又访问了已经被释放的资源的内容,这显然会引起程序崩溃,所以我们需要进行是否是自我赋值操作的验证,修改过后的函数如下
MyString& MyString::operator=(const MyString& rhs){
if(this==&rhs)
return *this;
delete [] str;
str=new char[strlen(rhs.str)+1];
strcpy(str,rhs.str);
return *this;
}
此时,函数虽然处理了自我赋值,但是仍然存在问题,如果new操作失败了怎么办?
我们已经释放了左操作数的资源,但是在重新分配资源时由于空间不够等原因失败了,如果我们继续对已经释放了的资源进行访问,会产生未定义的结果,赋值操作就不具备异常安全性,对于这个问题有两种解决方案
第一,调整语句顺序,先保存原来的资源,等重新分配资源完成以后再释放以前的资源
MyString& MyString::operator=(const MyString& rhs){
char *pTemp=str;
str=new char[strlen(rhs.str)+1];
strcpy(str,rhs.str);
delete [] pTemp;
return *this;
}
这段代码也能够处理自我赋值,但是必须执行完函数中的所有复制、分配和释放操作,如果自我赋值发生的概率比较高,我们也可以将测同语句放进该函数。
第二、采用copy and swap技术
MyString& MyString::operator=(const MyString& rhs){
if(this!=&rhs){
MyString temp(rhs);
char *pTemp=str;
str=temp.str;
temp.str=pTemp;
}
return *this;
}
这种技术赋值的是指针而不是为对象重新分配资源,我们在if语句内重新构造了一个新的临时对象,然后将临时对象的str和本类对象的str进行交换,当程序执行到if语句外时,临时对象自动调用析构函数,释放自己的资源,此时临时对象所持有的资源就是原来this所持有的资源,该资源得以释放,而现在this所持有的资源是rhs所持有的资源,即此时rhs和this中的str所指向的是同一块空间。
3、复制对象时切勿忘记复制其每一个元素
对于有继承关系的类,在对其派生类编写复制控制的函数时,由于派生类无法访问基类中的私有成员,所以在派生类的重载操作符函数中,需要首先调用其基类的赋值操作符函数对派生类中的基类成员进行赋值,然后再对派生类中的特有成员进行赋值。
C++重载赋值操作符的更多相关文章
- C++ 之 重载赋值操作符
Widget 类中,定义了一个 Bitmap 类型的私有数据成员 -- pb 指针 class Bitmap { ... }; class Widget { private: Bitmap *pb; ...
- C++中复制构造函数与重载赋值操作符总结
前言 这篇文章将对C++中复制构造函数和重载赋值操作符进行总结,包括以下内容: 1.复制构造函数和重载赋值操作符的定义: 2.复制构造函数和重载赋值操作符的调用时机: 3.复制构造函数和重载赋值操作符 ...
- C++中复制构造函数与重载赋值操作符
我们都知道,在C++中建立一个类,这个类中肯定会包括构造函数.析构函数.复制构造函数和重载赋值操作:即使在你没有明确定义的情况下,编译器也会给你生成这样的四个函数.例如以下类: class CTe ...
- 5.5 C++重载赋值操作符
参考:http://www.weixueyuan.net/view/6383.html 总结: 重载赋值操作符同重载类的是拷贝构造函数的原因是一样,将一个对象拷贝给另一个对象,同时当类中存在指针类型的 ...
- Effective C++(10) 重载赋值操作符时,返回该对象的引用(retrun *this)
问题聚焦: 这个准则比较简短,但是往往就是这种细节的地方,可以提高你的代码质量. 细节决定成败,让我们一起学习这条重载赋值操作符时需要遵守的准则吧. 还是以一个例子开始: Demo // 连锁赋值 x ...
- C++ 数组操作符重载、函数对象分析、赋值操作符
string类型访问单个字符 #include <iostream> #include <string> #include <sstream> using name ...
- C++中的赋值操作符重载和拷贝构造函数
1,关于赋值的疑问: 1,什么时候需要重载赋值操作符? 2,编译器是否提供默认的赋值操作符? 2,关于赋值的疑问: 1,编译器为每个类默认重载了赋值操作符: 1,意味着同类型的类对象可以相互赋值: 2 ...
- 【c++】c++中重载输出操作符,为什么要返回引用
针对:ostream & operator <<(ostream & os, const ClassType &object) 说明几点: 1.第一个形参为对ost ...
- [C++]复制构造函数、赋值操作符与隐式类类型转换
问题:现有类A定义如下: class A{public: A(int a) //构造函数 { ...
随机推荐
- LOJ 2172 「FJOI2016」所有公共子序列问题——序列自动机
题目:https://loj.ac/problem/2172 在两个序列自动机上同时走,这样暴搜. 先走字典序小的字符,一边搜一边输出,就是按字典序排序的. 方案数很多,需要高精度?空间很小,要压位. ...
- 【luogu P2065 [TJOI2011]卡片】 假题解
题目链接:https://www.luogu.org/problemnew/show/P2065 辣鸡匈牙利,没有优化贼鸡儿慢 // luogu-judger-enable-o2 #include & ...
- 【luogu P2299 Mzc和体委的争夺战】 题解
题目链接:https://www.luogu.org/problemnew/show/P2299#sub 裸的迪杰斯特拉(我是在考试前复习一下板子) #include<iostream> ...
- 发布Android程序
这个选项的意思是说,要使用.NET 2.0的完整版本,而非其子集. 下午发布Apk,一直报错,解决好了,忘记选这个了,以前都记得,明天再去公司发布去
- SpringBoot非官方教程 | 第十一篇:springboot集成swagger2,构建优雅的Restful API
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot-swagger2/ 本文出自方志朋的博客 swa ...
- 优雅的QSignleton (一) Singleton单例实现
接下来笔者来介绍如何用QSingleton实现一个简单的单例. 代码如下. Singleton.cs namespace QFramework.Example { using UnityEngine; ...
- Oracle PL/SQL中异常高级特性
在OraclePL/SQL语句块中exception的异常处理部分是非常重要的组成部分,它决定了在PL/SQL语句块内部可执行部分在发生异常错误时,程序是友好地提示:程序遇到某些错误而无法执行,还是抛 ...
- IOS 浅谈闭包block的使用
前言:对于ios初学者,block通常用于逆向传值,遍历等,会使用,但是可能心虚,会感觉block很神秘,那么下面就一起来揭开它的面纱吧. ps: 下面重点讲叙了闭包的概念,常用的语法,以及访问变量, ...
- iOS之Xcode自动管理证书、打包adhoc和testFlight测试安装
引言:Xcode8 之后引用Automatic manage signing .对于开发者而言,在证书上栽的坑肯定不少. 准备:1.开发者账号是必须的吧. 2. Xcode设置account (不给 ...
- jquery mobile 移动web(4)
下拉菜单: 设置label 元素的for 属性为 select label 元素的文本内容作为选项的名称 定义div元素并设置data-role 属性值为 fieldcontain. <div ...