操作符重载01--赋值运算符(Assignment Operator =)

一直对c++的操作符重载都迷迷糊糊,因为用的也少,有时间就系统的看看。

赋值运算符(=)使用非常频繁,就是将一个值或一个变量赋值给另外一个同类型或者相似类型的变量。我们自己写的类和结构体都会有四个默认函数(default functions)假如我们不定义的话:构造函数(default constructor)、拷贝构造函数(copy constructor)、析构函数(destructor)以及赋值运算符(assignment operator)。

测试code如下:

TRectangle.h

   1: #pragma once
   2:  
   3: //赋值运算符重载要点
   4: /*
   5: 1. 返回类的引用
   6: 2. 参数最好使用const修饰,最好也使用引用类型
   7: 3. 判断是不是本身赋值,尤其是有指针的情况
   8: 4. 如果是地址,不能直接地址赋值,而是应该另外copy一份
   9: */
  10: class TRectangle
  11: {
  12: public:
  13:     TRectangle(double dL = 0, double dH = 0);
  14:     TRectangle(TRectangle& R);
  15:     ~TRectangle(void);
  16:  
  17:     //method
  18:     void setLength(const double dL){ m_dLength = dL; }
  19:     void setHeight(const double dH){ m_dHeight = dH; }
  20:  
  21:     double getLength(){ return m_dLength; }
  22:     double getHeight(){ return m_dHeight; }
  23:  
  24:     //assignment operator
  25:     TRectangle& operator=(const TRectangle& R);
  26: private:
  27:     double m_dLength;
  28:     double m_dHeight;
  29: };
  30:  

TRectangle.cpp

   1: #include "StdAfx.h"
   2: #include "TRectangle.h"
   3:  
   4:  
   5: TRectangle::TRectangle(double dL, double dH) : 
   6: m_dLength(dL),
   7: m_dHeight(dH)
   8: {
   9: }
  10:  
  11: TRectangle::TRectangle(TRectangle& R) :
  12: m_dLength(R.m_dLength),
  13: m_dHeight(R.m_dHeight)
  14: {
  15: }
  16:  
  17: TRectangle::~TRectangle(void)
  18: {
  19: }
  20:  
  21: TRectangle& TRectangle::operator=(const TRectangle& R)
  22: {
  23:     if(this == &R) return (TRectangle&)R;
  24:     m_dLength = R.m_dLength;
  25:     m_dHeight = R.m_dHeight;
  26:     return *this;
  27: }

main()

   1: // AssignmentOperator.cpp : 定义控制台应用程序的入口点。
   2: //
   3:  
   4: #include "stdafx.h"
   5: #include <iostream>
   6: #include "TRectangle.h"
   7:  
   8:  
   9: int _tmain(int argc, _TCHAR* argv[])
  10: {
  11:     TRectangle Ra, Rb;
  12:     Ra.setLength(10);
  13:     Ra.setHeight(5);
  14:  
  15:     Rb.setLength(100);
  16:     Rb.setHeight(50);
  17:  
  18:     std::cout << "Rectangle A  Length is " << Ra.getLength() << ",Height is " << Ra.getHeight() << std::endl;
  19:     std::cout << "Rectangle B  Length is " << Rb.getLength() << ",Height is " << Rb.getHeight() << std::endl;
  20:  
  21:     Ra = Rb;
  22:     std::cout << "Rectangle A  Length is " << Ra.getLength() << ",Height is " << Ra.getHeight() << std::endl;
  23:  
  24:     return 0;
  25: }

结果如下:

image

转载于:https://www.cnblogs.com/maogeblog/archive/2012/09/12/2682061.html

### C++ 构造函数与赋值运算符的区别 #### 一、概念差异 构造函数是一种特殊的成员函数,在创建对象时被自动调用,其目的是初始化新创建的对象。而赋值运算符则是在两个已有对象之间进行数据传递时使用的操作符重载方法。 - **拷贝构造函数**:当需要通过已有的对象来初始化一个新的对象时,会调用拷贝构造函数[^2]。 - **赋值运算符**:如果目标对象已经存在,则使用赋值运算符将其内容替换为另一个对象的内容[^3]。 --- #### 二、调用场景对比 | 场景 | 调用方式 | |------|----------| | 创建并初始化一个新对象 | 拷贝构造函数 | | 将现有对象的数据赋给另一个已存在的对象 | 赋值运算符 | 具体来说: 1. 当以下情况发生时,会触发拷贝构造函数: - 函数参数按值传递时; - 返回局部对象时; - 显式地用一个对象去初始化另一个对象时[^4]。 2. 对于赋值运算符而言,它会在如下条件下被调用: - 已经声明好的对象重新获得其他对象的值时;例如 `objA = objB` 这样的语句中。 --- #### 三、实现细节比较 ##### (1) 拷贝构造函数 通常定义形式如下所示: ```cpp ClassName(const ClassName& other); ``` 需要注意的是,为了避免潜在的风险(比如指针指向同一内存区域),可能还需要考虑深拷贝逻辑而不是默认的浅拷贝。 示例代码展示如何正确编写带资源管理功能的类及其拷贝构造函数: ```cpp class MyClass { private: int* data; public: explicit MyClass(int value) : data(new int(value)) {} ~MyClass() { delete data; } // Copy Constructor with deep copy logic. MyClass(const MyClass& other) : data(new int(*(other.data))) {} }; ``` 上述例子展示了手动分配动态存储空间的情况,并且确保了每次复制都能独立拥有自己的副本。 ##### (2) 赋值运算符 一般形式为: ```cpp ClassName& operator=(const ClassName& rhs); ``` 同样重要的一点是防止自我赋值带来的问题以及执行必要的清理工作后再做实际的赋值动作。 下面给出完整的带有安全机制版本的例子: ```cpp #include <iostream> using namespace std; class String { private: char *str; public: String(): str(nullptr){} String(const char*s){ if(s != nullptr){ this->str=new char[strlen(s)+1]; strcpy(this->str,s); } } ~String(){ cout << "~String()" << endl; delete []this->str; } // Assignment Operator Overloading String& operator= (const String &rhs){ if(&rhs == this)return *this;// Self assignment check delete[] this->str; // Release current resource first. if(rhs.str!=nullptr){ this->str=new char[strlen(rhs.str)+1]; strcpy(this->str,rhs.str); }else{ this->str=nullptr; } return *this; } }; int main(){ String s1("hello"); String s2="world"; s2=s1; } ``` 此程序片段不仅实现了字符串类型的简单封装还包含了对赋值过程中的异常处理措施。 --- ### 总结 综上所述,虽然两者看起来相似但实际上用途完全不同——前者负责构建新的实例后者则是更新现有的实体状态[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值