您的位置:首页 > 编程语言 > C语言/C++

为什么有时候C++运算符重载要返回引用,附对象生存周期

2017-08-31 15:36 302 查看
ヽ(・ω・。)ノ这个问题好几次想起来要记下来 结果都给忘了,写在这里以防哪天手误删了word里的笔记。

---------------------------------------------------------

原因如下:

(1)允许连续赋值,举个栗子:

class CMyString//咳,就拿上课讲过的代码好了
{
public:
CMyString(char *ptr=NULL)  
{
if(ptr != NULL)
{
mpStr = new char[strlen(ptr)+1];
strcpy(mpStr, ptr);
}
else
{
mpStr = new char[1];
*mpStr = 0;
}
}
CMyString(const CMyString &src)
{
mpStr = new char[strlen(src.mpStr)+1];
strcpy(mpStr, src.mpStr);
}
CMyString& operator=(const CMyString &src)
{
if(this == &src)
return *this;

delete []mpStr;

mpStr = new char[strlen(src.mpStr)+1];
strcpy(mpStr, src.mpStr);
return *this;
}
//等号重载要记得(1)判断自赋值(2)释放原空间(3)重新申请空间并赋值。
~CMyString()
{
delete []mpStr;
mpStr = NULL;
}

bool operator>(const CMyString &src)
{
return strcmp(mpStr, src.mpStr) > 0;
}
bool operator<(const CMyString &src)
{
return strcmp(mpStr, src.mpStr) < 0;
}
bool operator==(const CMyString &src)
{
return strcmp(mpStr, src.mpStr) == 0;
}
   
char& operator[](int index){return mpStr[index];}  //通过下标访问不仅要实现读的功能也要具有写的功能
private:
char *mpStr;

friend ostream& operator<<(ostream &out, 
const CMyString &src);

friend CMyString operator+(const CMyString &lhs,
const CMyString &rhs);
//嘛,参数加const不仅是为了防止“原版”被改变也是为了让它既能接收const形参也能接受非const参数
//那为什么加引用呢?这样可以防止传参时对参数进行拷贝以提高效率
};
CMyString operator+(const CMyString &lhs,   const CMyString &rhs)
{
int size = lhs.size() + rhs.size() + 1;
char *p = new char[size];
strcpy(p, lhs.mpStr);
strcat(p, rhs.mpStr);
CMyString temp(p);
delete []p;
return temp;
}
ostream& operator<<(ostream &out, const CMyString &src)
{
out<<src.mpStr;return out;
}
int main()
{
CMyString str1 = "aaa";
CMyString str2 = "bbb";
CMyString str3 = str1 = str2;//通过重载实现连续赋值
cout<<"str1"<<str1<<endl;
cout<<"str2"<<str2<<endl;
str3[2] = 'p';//通过下标实现赋值
cout<<str3[2]<<endl;//通过下表实现访问
cout<<"str3"<<str3<<endl;
}

(2)防止返回对象时调用拷贝构造函数、析构函数产生额外开销。

-------------------------------------------------------------------

(,,• ₃ •,,)嗨呀返回引用原来效率这么高!但是要当心不能不分场合的返回引用。
比如:不可以返回一个局部变量的引用,它的生存周期只在函数体内。

现在,如果要返回一个对象,值得注意的是我们最好返回一个临时对象。
由于C++编译器的优化功能会直接在主函数栈帧上拷贝构造新对象而减少产生一个临时对象的构造、析构开销。

临时对象和局部对象可不一样!临时对象就是没有名字的对象,它的生存周期只存在于当前语句。
当然有种情况例外,假设我们现在有一个类Test,
Test &p = Test(); //产生临时对象,使p成为它的别名,对象不会马上析构而是等离开p的作用域才析构。 

---------------------------------------------------------------------------------------------------------------
既然提到临时对象局部对象就顺便记下对象生存周期:

//对象生存周期

class Test

{

public:

Test(int a=5, int b=5):ma(a), mb(b)//带默认值

private:

int ma;

int mb;

};

Test t1(10,10);                   //构造t1

                                  //构造t5

int main()

{

Test t2(20,20);                   //构造t2   

Test t3 = t2;                     //t2拷贝构造t3

static Test t4 = Test(30,30);     //直接构造t4(这里有个编译器优化)

t2 = Test(40,40);                
//构造临时对象给t2赋值,临时对象析构

t2 = (Test)(50,50);              
//构造临时对象Test(50)给t2赋值,临时对象析构

t2 = 60;                         
//构造临时对象Test(60)给t2赋值,临时对象析构

Test *p1 = new Test(70,70);      
//堆上 构造对象

Test *p2 = new Test[2];          
//堆上 构造数组对象Test()

Test *p3 = &Test(80,80);          //构造临时对象,临时对象析构

Test &q = Test(90,90);           
//构造局部对象,使q成为它的别名

delete p1;                       
//p1析构

delete []p2;                     
//p2析构

}

                                  //p4,t3,t2,t4,t5,t1析构

Test t5(100,100);

--------------------------------------------------------------------------------------------------------------
先写这么多=。=以免字太多自己都看不下去,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐