关闭

返回值的理解

749人阅读 评论(0) 收藏 举报

返回值的理解

class A

{

……..

};

一直以来搞不清“返回值”这个概念,今天总算搞清楚了。

我们知道返回值有三种方式:

第一种:“普通”方式,例如,

 A fun()

 {

     A a;

     ...

     return a;

 }

第二种:const方式,例如

      const A fun()

   {

          A a;

            ...

           return a;

   }

第三种:const+引用方式,例如

 const A& fun(const A& a)

 {  

        ...        

        return a;

 }

首先我们得弄清楚返回值的机制,我们做一下测试:

#include <iostream.h>

class A

{

public:

       int a;

       int b;

       static int cnt;//调用次数

       A();

       A(const A &rhs);

};

int A::cnt = 1;

A::A()

{

       a = 0;

       b = 0;

       cout<<this<<endl;

       cout<<"Construct be performanced "<<cnt<<" times."<<endl;

       cnt++;

}

A::A(const A &rhs)

{

       cout<<this<<endl;

       cout<<"Copy Construct be performanced"<<endl;

       a = rhs.a;

       b = rhs.b;

}

const A Fun()

{

       A aa;

       return aa;

}

int main()

{

       A bb = Fun();

       return 0;

}

1

程序的运行结果是,构造函树调用了1次、拷贝构造函数被调用了2次,输出了三个不同的this指针的地址,因此我们可以得出结论,整个程序在运行过程钟产生了三个对象。其中的两个对象是显而易见的,一个是Fun()中的aa,一个是main()中的bb,那么还有一个是哪里来的呢。是返回值,以前对我返回值的理解“fun ()的返回值 == aa”,现在看来是错误的。在bbfunc()赋值之前,编译器生成了一个返回值。

为了进一步证明我们把main()函数改为:

int main()

{

       cout<<Fun().a<<endl;

       return 0;

}

运行结果:

第二个地址值就是返回值(对象)所在的地址。

第三中方式因为传回的是引用,“fun ()的返回值 == aa”在这种情况是成立的。我们把fun()改为:

const A& Fun()

{

       A aa;

       return aa;

}

这时的运行结果

不过这样做存在一个巨大的隐患,如果把A bb = Fun();改为

A &bb = Fun();

因为aa是一个局部变量,它的生命周期在A &bb = Fun();语句子后就结束了。这时如果编译程序将报错。

结论:

1.当函数带返回值时,有一个看不见的返回值变量

2,返回值的第一种方式和第二种方式的区别是第二种方式中返回值是const型的,在直接用返回值不可改变其值

3.对于A bb = fun ()这样的语句(fun()的返回值采用的是第一种和第二种方式),是直接调用拷贝构造函数而非赋值运算符。

4.第三种方式可认为“fun ()的返回值 == aa”,但应注意return后的变量不为局部变量,如果是动态变量(在堆上申请内存),应注意delete,建议不要这么用,

因为newdelete不在同一个函数中,很容易被遗忘。

 

 

这里引发我的另一个问题,为什么A bb = fun() 调用的是拷贝构造函数而不是赋值运算符。我猜测是不是赋值函数调用了拷贝函数(其实稍加推敲就知道这个想法是错误的,因为调用一个拷贝构造函数就意味新生成了一个对象,而在调用赋值运算符之前,肯定已经调用了一个构造函数,而一个对象是不可能调用类的两个构造函数的(指同一个类的两个构造函数))。为了弄清这个问题,我为class A 重载了“=”运算符:

const A A::operator=(const A& rhs)

{

       cout<<this<<endl;

       cout<<"Evaluate function be performanced"<<endl;

       a = rhs.a;

       b = rhs.b;

       return *this;

}

但运行的结果依然与(1)一样。但如果把 A bb = fun();改为

A bb;

       bb = Fun();

这时的运行结果

调用了普通构造函数和赋值运算符。因此得出结论:

bb = fun();

A bb;

       bb = Fun();

的运行方式是不一样的。

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:16344次
    • 积分:229
    • 等级:
    • 排名:千里之外
    • 原创:3篇
    • 转载:3篇
    • 译文:0篇
    • 评论:4条
    文章分类
    最新评论