返回值的理解

原创 2006年05月29日 16:44:00

返回值的理解

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();

的运行方式是不一样的。

 

相关文章推荐

关于对于C语言中主函数参数接返回值的理解

main函数的返回值 main函数的返回值用于说明程序的退出状态。如果返回0,则代表程序正常退出;返回其它数字的含义则由系统决定。通常,返回非零代表程序异常退出。 很多人甚至市面上的一些书籍,都使...

CMystring类实现以及返回值的理解

///////////////////////////////////////////////////////////////////// // Filename: mystring.h //////...

C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解)

C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解) 引用与指针的比较 引用是 C++中的概念,初学者容易把引用和指针混淆一起。一下程序中,n 是m 的 一个引用(refe...

探讨c++函数中的参数传递与返回值(一) 概念介绍与理解

本文从编译器角度,通过反汇编手段,深入的理解了1.引用的理解与使用2.结构体和类做参数时的底层实现,并对函数参数和返回值的各种情况做了归纳。希望能对大家有用,也希望大家能针对本文中的一些不足和缪误给予...

深入理解主函数main()的输入参数及返回值问题

C语言之Main函数返回值问题分析: 很多人甚至市面上的一些书籍,都使用了void main( ) ,其实这是错误的。C/C++ 中从来没有定义过void main( ) 。C++ 之父 Bjarne...
  • zyazky
  • zyazky
  • 2016年09月22日 11:37
  • 276

fork()返回值两个的根本理解!!!

2011-03-07 22:52 对于fork来说,父子进程共享同一段代码空间,所以给人的感觉好像是有两次返回,其实对于调用fork的父进程来说,如果fork出来的子进程没 有...

关于函数返回值的一些理解

前面看了几篇关于函数返回值的帖子,觉得学多了高级程序语言,还是有必要对一些底层的只是需要了解一些 下面我总结了一些,肯定是不全,还望大家给予指正O(∩_∩)O~ 当我们使用一个被调函数的时候,re...

帮助大家理解一下递归函数的返回值...

如题: 递归函数往往可以简化我们的代码,尤其是对树的遍历和利用回溯算法写代码的时候,但是递归函数的返回值往往是困扰我们的。 总体来说,我们先要理解函数的调用过程,函数调用过程会用栈来保存函数的返回...

通过IL理解C# try catch finally中真正的return 返回值

通过分析IL流程和画IL流程图 来分析try finally 中真正的return的返回值

unity3d 协程的初步理解 - 支持返回值/支持异常处理/支持泛型

能告诉我什么是协程吗? 协程的官方定义是一种具有暂停执行并将控制权返回给Unity,待下一帧时继续执行。通俗点讲就是,协程是一种可以分部执行的函数,即该函数不是每次调用时都会执行函数体内的全...
  • ybhjx
  • ybhjx
  • 2017年02月15日 09:31
  • 613
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:返回值的理解
举报原因:
原因补充:

(最多只允许输入30个字)