运算符函数
在C++中会把运算符当作函数处理,一个表达式其实是调用了运算符函数完成计算的,这种特性对内建的数据类型没什么用,但对自建的数据类型却可以提高它们的个性化,从而提高代码的易用性和可读性,如:
string str;
str += "hehe";
str == "xixi";
运算符格式
运算符格式:
单目运算符:#0、0#会被编译器翻译成如下形式
成员函数:
返回值 类名::operator<运算符>(参数)
{
}
全局函数:
返回值 operator<运算符>(类名&,参数)
{
}
注意:运算符的成员函数和全局函数只能实现一个,否则会冲突。
双目运算符:a#b(以左边的类型为主)
成员函数:
返回值 A:: operator#(const B&b)
{
}
全局函数:
返回值 operator#(const A& a,const B& b)
{
}
双目运算符重载
成员函数:a+b
const T operator+(const T& b)[const]
{
T tmp(this->成员+b.成员);
return tmp;
}
全局函数:a+b
const T operator+(const T& a,const T& b)
{
T tmp(a.成员+b.成员);
return emp;
}
注意:如果在全局函数使用到了类的私有成员,可以给全局函数加上友元声明(前加friend),这样该函数就可以使用类的私有成员。
注:如果全局和成员都重载了,那么会冲突。
输入、输出运算符重载
输出、输入运算符重载:
friend ostream& operator<<(ostream& os,const T& t)
{
return os << t.xxx;
}
friend istream& operator>>(istream& is,T& t)
{
return is >> t.xxx;
}
注意:由于双目运算符是由左边运算对象触发成员运算符,所以如果想把<<,>>运算符重载为成员运算符函数则必须在ostream、istream类的代码,但这两个类的代码已经封装在C++的的标准库中无法修改,所以必须重载为全局函数。
注意:友元不是成员函数(友元函数虽然在类中声明,但是属于全局),没有this指针,所以必须通过对象.成员函数。
自变运算符重载
前自变运算符:++/--i
成员函数:
const T& operator++(void)
{
t.xxx++;
return *this;
}
全局函数:
const T& operator++(T& t)
{
t.xxx++;
return t;
}
后自变运算符:i++/--
成员函数:
const T operator++(int)
{
T t = *this;
this->xxx++;
return t;
}
全局函数:
const T operator++(T& t,int)
{
t.xxx++;
return t;
}
注意:用哑元(指参数里面的那个光秃秃的int)区别后自变运算符函数。
特殊运算符的重载
1、<< >> 既可以重载为输入输出,也可以重载为左移和右移。
2、->间接成员访问运算符/ *解引用运算符
重载这两个运算符的目的是为了让对象可以像指针一样使用。
3、[] 下标运算符
重载该运算符的目的是为了让对象像数组一样使用。
4、() 函数调用运算符
重载该运算符的目的是为了让对象像函数一样使用。
5、new/delete重载
1、new/delete重载后,可以在重载函数中记录分配、和释放的内存地址,用于检查 内存泄漏。
2、对于分配的字节数据较小的内存块,可以在原来的基础上多分配一些,尽量减少内存碎片的产生,但同时也会浪费一部分内存。
3、重载为成员和全局函数的格式相同,只是作用范围不同
重载为成员函数,只有该类可以用。
重载为全局函数,所有类型都可以使用。
void* operator new(size_t len)
{
// len = len<8 ? 8 : len; 减少内存碎片的产生
void* ptr = malloc(len);
cout << "malloc:" << ptr << endl;
return ptr;
}
void operator delete(void* ptr)
{
free(ptr);
cout << "free:" << ptr << endl;
ptr = NULL;
}
运算符重载的限制
1、不能重载的运算符
:: 域限定符
. 直接成员访问运算符
?: 三目运算符
sizeof 字节数运算符
typeid 类型信息运算符
2、只能重载为全局函数的运算符
>> 输入运算符
<< 输出运算符
3、只能重载为成员函数的运算符
[] 下载运算符
= 赋值运算符
-> 间接成员访问运算符
4、运算符重载时可以自定义运算符函数的计算过程,但无法改变运算符的优先级。
5、无法改变运算符的操作对象的个数。
6、不能发明新的运算符。
注意:
1、重载运算符要符合情理。
1、重载运算符时要遵循一致性,不要改变运算符的运算规则。
2、重载运算符是为了提高代码的可读性、易用性。
智能指针
常规指针的缺点:
当常规指针离开它的作用域时,该指针所占用4|8字节的内存会被释放,而指针所指向堆内存可能,忘记执行free、delete、delete[],或者条件判断出现问题无法执行,这样就会导致内存泄漏。
什么智能指针:
智能指针就是封装了常规指针的类对象,并且选项*,->运算符。
当智能指针离开作用域时,会自动调用它的析构函数,在析构函数中释放常规指针所指向的堆内存,从而避免内存泄漏。
智能指针的缺点:
1、不能跨作用域使用
2、不能多个指针指向一个对象
3、不能指向数组型对象
4、不能放入容器
C++中智能指针的使用方法:C++98
#include <memory>
auto_ptr<类型> ptr(new 类型);