导航

关于返回对象

Posted on 2009-05-16 01:31  无意乂  阅读(1269)  评论(0编辑  收藏  举报

函数返回对象有两种常见的方式

1.重载拷贝构造函数和赋值函数
  见下面的fun1
2.重载赋值函数,然后用"return <构造函数>"的格式
  见下面的fun2

测试代码.对类C重载了赋值运算,构造,析构,拷贝构造.然后写了两个函数来测试返回值

class C
{
public:
    
int i;
    C 
&operator = (C &o)    //赋值
    {
        i 
= o.i;
        cout
<<"C &operator = (C &o) "<<i<<endl;
        
return *this;
    };
    C(
int p)        //构造
    {
        i 
= p;
        cout
<<"C() "<<i<<endl;
    };
    
~C()            //析构
    {
        cout
<<"~C() "<<i<<endl;
    };
    C(C 
&o)        //拷贝构造
    {
        i 
= o.i*10;
        cout
<<"C(C &o) "<<i<<endl;
    };
};

C fun1()
{
    
return C(1);
}

C fun2()
{
    C o(
2);
    
return o;
}

void main()
{
    C o(
3);
    cout
<<"---fun1---"<<endl;
    o 
= fun1();
    cout
<<"---fun2---"<<endl;
    o 
= fun2();
    cout
<<"---main---\no.i = "<<o.i<<endl;
    system(
"PAUSE");
}


运行结果

C() 3
---fun1---
C() 
1
C &operator 
= (C &o) 1
~C() 
1
---fun2---
C() 
2
C(C &o) 
20
~C() 
2
C &operator 
= (C &o) 20
~C() 
20
---main---
o.i 
= 20
请按任意键继续. . .

 可见.fun1内共生成了一个临时对象.函数调用顺序是

return用的临时对象的构造->赋值运算传值->临时对象的析构

fun2内共生成了两个临时对象.效率较低,但便于修改.函数调用顺序是

fun2内局部对象的构造->return用的临时变量的拷贝构造->局部对象的析构->赋值运算传值->临时对象的析构

 

fun2的效率较低,但便于修改;fun1又要有构造函数的支持才行

 

如果返回引用的话,就没有这么多临时变量了.但是返回值为某一类型的引用一般是为了实现链式表达.而且有下面几点要注意:
1.不能返回局部变量的引用.因为在外面的对象接到这个引用之前就已经被析构掉了.它只能接到一个空对象
2.不要返回函数内部new分配的内存的引用.因为delete的安排会变得麻烦,而且很容易造成内存泄漏或访问到已经delete的对象
3.可以返回类成员的引用,但最好是const
4.不要返回静态变量的引用.比如,operator+返回了静态变量的引用.((a+b) == (c+d))会永远为true而导致错误
详细的可以参考这里.好像是Effective C++里面的内容吧

 

其实我就经常不返回对象而是返回new得到的对象的指针.管理起来相当麻烦...也许这是一种坏习惯吧,改改好了
又被蚊子咬了..郁闷.