this指针
-
**实质:**指向当前对象本身
-
**存在:**隐含在每一个非静态成员函数的第一个参数的位置 ,由编译器自动补全。
-
**形式:**类类型 * const this,例如:Point * const this
指针常量:无法改变指向,可以改变所指内容值。
-
对于类成员函数而言,此类的所有对象共用一个成员函数体。
当程序被编译之后,成员函数地址即已确定。
而成员函数之所以能把属于此类的各个对象的数据区别开, 就是靠this指针。
函数体内所有对类数据成员的访问, 都会被转化为
this->数据成员
的方式。
举例代码:
//print函数的完整实现是:
void Point::print(Point *const this)
{
cout << "(" << this->_ix << "," << this->_iy << ")" << endl;
this = nullptr; //error
this = 0X7ffffff;//error
this->_ix = 10;//OK
}
赋值运算符函数
-
当“ = ”作用于对象时,将其看做一个函数,即赋值运算符函数。
-
格式:
返回类型 类名::operator = (参数列表){ //······ }
-
存在形式:
- 默认赋值运算符函数(编译器自动提供)
- 自定义赋值运算符函数
举例代码:
//Point类
Point &Point::operator=(const Point &rhs)
{
_ix = rhs._ix;
_iy = rhs._iy;
return *this;
}
//Computer类 —— 浅拷贝
Computer &Computer::operator=(const Computer &rhs)
{
_brand = rhs._brand;
_price = rhs._price;
return *this;
}
//即系统默认的赋值运算符函数是浅拷贝形式的;若想要以深拷贝形式存在,复制空间内容值,则需要自己显式定义。
//Computer类 —— 深拷贝
//注意:返回类型为引用变量
Computer &Computer::operator=(const Computer &rhs){
//不能使用*this!=rhs,因为这样是在比较两个对象是否相等,但是两个对象是不能用赋值符号=来比较的。
if(this != &rhs){ //第一步:防止自复制
delete [] _brand; //第二步:释放左操作数,防止内存泄漏
_brand = nullptr;
_brand = new char[strlen(rhs._brand) + 1](); //第三步:深拷贝赋值
strcpy(_brand, rhs._brand);
_price = rhs._price;
}
return *this; //第四步:返回*this,因为返回值类型为对象类型,所以要解引用。
}
赋值运算符函数“四步曲”
- 防止自复制, 防止自己复制给自己。
- 释放左操作数:如果不释放,可能导致内存泄漏。
- 深拷贝:深拷贝赋值对象数据成员。如果直接拷贝,可能因为右操作数比左操作数空间大,而内存溢出。
- 返回*this 返回对象本身
问题总结
赋值运算符函数的参数中引用可以去掉吗?
不能,会多调用一个拷贝构造函数,影响效率
赋值运算符函数的参数中const可以去掉吗?
当赋值时,右操作数是右值时候,识别不了。
赋值运算符函数的返回类型中的引用可以去掉吗?
**不可以去掉,**否则会多调用一个拷贝构造函数,影响效率。
**调试:**符合拷贝构造函数调用时机3。赋值运算符函数的返回类型可以不是类类型吗?
不能,因为若出现连等情况:pt1 = pt2 = pt3
,
此时先执行:pt2 = pt3
,返回Point类型,再将pt1 = 返回值
,若返回的是其他类型,则第二次连等时会出现数据类型不匹配的情况。