C++中大致有三种返回值:值拷贝(副本),值引用和指针,返回什么类型的值要根据当时情况而定。

如果返回的是大型对象的副本,那么在每一次的函数调用后返回,都会调用该对象类型的拷贝构造函数构造一个新的副本,这是一个耗时的过程。

因此在不需要返回对象副本的时候,尽量返回对象的引用或者指针,与此同时,如果不会改变引用或者指针指向的对象的内容,都加上const限定符。

不论是返回拷贝,引用还是指针,返回值都会作为左值来使用,因此也可以将返回值赋值给其他变量(类型可以是值类型,引用类型或者指针类型)

实例:

class Widget
{
public:
Widget()
{
a = 0;
printf("Widget constructor with default value: this:%p a:%d \n", this, a);
}
Widget(int v)
{
a = v;
printf("Widget constructor with parameters: this:%p a:%d \n", this, a);
}
Widget(const Widget& widget)
{
this->a = widget.a;
printf("Widget copy constructor with reference: this:%p widget:%p a:%d \n", this, &widget, a);
}
Widget(const Widget* widget)
{
this->a = widget->a;
printf("Widget copy constructor with pointer: this:%p widget:%p a:%d \n", this, widget, a);
}
Widget& operator = (const Widget& widget)
{
this->a = widget.a;
printf("Widget operator =: this:%p widget:%p a:%d \n", this, &widget, a); return *this;
}
Widget& operator + (const Widget& widget)
{
this->a += widget.a;
printf("Widget operator +: this:%p widget:%p a:%d \n", this, &widget, a); return *this;
}
Widget getByCopy()
{
printf("Widget get object by copy: this:%p a:%d \n", this, a); return *this;
}
Widget& getByRef()
{
printf("Widget get object by ref: this:%p a:%d \n", this, a); return *this;
}
Widget* getByPointer()
{
printf("Widget get object by pointer: this:%p a:%d \n", this, a); return this;
} int a;
};
int _tmain(int argc, _TCHAR* argv[])
{
Widget w1(1); // 调用构造函数 Widget(int v)
Widget w2(2);
Widget w3; // 调用默认构造函数
w3 = (w1 + w2); // 先调用+操作符,在调用=操作符 printf("\n");
printf("w4 -------------------- \n");
w3.getByCopy(); // 返回副本
printf("w4_1 -------------------- \n");
Widget w4_1 = w3.getByCopy(); // 感觉应该会有两次拷贝,实际只有一次Widget(const Widget& widget)拷贝构造函数的调用,估计是编译器的优化
printf("w4_2 -------------------- \n");
Widget w4_2;
w4_2 = w3.getByCopy(); // 先调用Widget(const Widget& widget)拷贝构造函数,再调用=赋值拷贝函数
printf("w4_3 -------------------- \n");
Widget& w4_3 = w3.getByCopy(); // 调用一次Widget(const Widget& widget)拷贝构造函数
printf("-------------------- \n\n"); printf("w5 -------------------- \n");
w3.getByRef(); // 返回引用
printf("w5_1 -------------------- \n");
Widget w5_1 = w3.getByRef(); // 调用一次Widget(const Widget& widget)拷贝构造函数
printf("w5_2 -------------------- \n");
Widget w5_2;
w5_2 = w3.getByRef(); // 没有调用拷贝构造函数,调用一次=赋值拷贝函数
printf("w5_3 -------------------- \n");
Widget& w5_3 = w3.getByRef(); // 直接赋值给引用
printf("-------------------- \n\n"); printf("w6 -------------------- \n");
w3.getByPointer(); // 返回指针
printf("w6_1 -------------------- \n");
Widget w6_1 = w3.getByPointer(); // 调用一次Widget(const Widget* widget)拷贝构造函数
printf("w6_2 -------------------- \n");
Widget w6_2;
w6_2 = w3.getByPointer(); // 由于没有针对指针的赋值拷贝函数,先调用拷贝构造函数,创建一个临时变量,再调用=赋值拷贝函数
printf("w6_3 -------------------- \n");
Widget* w6_3 = w3.getByPointer(); // 直接赋值给指针
printf("-------------------- \n"); getchar(); return 0;
}

运行结果:

Widget constructor with parameters: this:0035FB70 a:1
Widget constructor with parameters: this:0035FB64 a:2
Widget constructor with default value: this:0035FB58 a:0
Widget operator +: this:0035FB70 widget:0035FB64 a:3
Widget operator =: this:0035FB58 widget:0035FB70 a:3 w4 --------------------
Widget get object by copy: this:0035FB58 a:3
Widget copy constructor with reference: this:0035F9FC widget:0035FB58 a:3
w4_1 --------------------
Widget get object by copy: this:0035FB58 a:3
Widget copy constructor with reference: this:0035FB4C widget:0035FB58 a:3
w4_2 --------------------
Widget constructor with default value: this:0035FB40 a:0
Widget get object by copy: this:0035FB58 a:3
Widget copy constructor with reference: this:0035FA08 widget:0035FB58 a:3
Widget operator =: this:0035FB40 widget:0035FA08 a:3
w4_3 --------------------
Widget get object by copy: this:0035FB58 a:3
Widget copy constructor with reference: this:0035FB28 widget:0035FB58 a:3
-------------------- w5 --------------------
Widget get object by ref: this:0035FB58 a:3
w5_1 --------------------
Widget get object by ref: this:0035FB58 a:3
Widget copy constructor with reference: this:0035FB1C widget:0035FB58 a:3
w5_2 --------------------
Widget constructor with default value: this:0035FB10 a:0
Widget get object by ref: this:0035FB58 a:3
Widget operator =: this:0035FB10 widget:0035FB58 a:3
w5_3 --------------------
Widget get object by ref: this:0035FB58 a:3
-------------------- w6 --------------------
Widget get object by pointer: this:0035FB58 a:3
w6_1 --------------------
Widget get object by pointer: this:0035FB58 a:3
Widget copy constructor with pointer: this:0035FAF8 widget:0035FB58 a:3
w6_2 --------------------
Widget constructor with default value: this:0035FAEC a:0
Widget get object by pointer: this:0035FB58 a:3
Widget copy constructor with pointer: this:0035FA14 widget:0035FB58 a:3
Widget operator =: this:0035FAEC widget:0035FA14 a:3
w6_3 --------------------
Widget get object by pointer: this:0035FB58 a:3
--------------------

  

C++ 中的返回值的更多相关文章

  1. Asp.net MVC 中Controller返回值类型ActionResult

    [Asp.net MVC中Controller返回值类型] 在mvc中所有的controller类都必须使用"Controller"后缀来命名并且对Action也有一定的要求: 必 ...

  2. [改善Java代码]不要在finally块中处理返回值

    在finally代码块中处理返回值,这是在面试题中经常出现的题目.但是在项目中绝对不能再finally代码块中出现return语句,这是因为这种处理方式非常容易产生"误解",会严重 ...

  3. Controller 中Action 返回值类型 及其 页面跳转的用法

        •Controller 中Action 返回值类型 View – 返回  ViewResult,相当于返回一个View 页面. -------------------------------- ...

  4. robot framework中的返回值

    1.若想要再setup中有返回值,给后续的操作使用 A)在setup的关键词中需要的返回值,设置为global variable或者suit variable:如下图:但是在编译器中,会报错,但是执行 ...

  5. Web API中的返回值类型

    WebApi中的返回值类型大致可分为四种: Void/ IHttpActionResult/ HttpResponseMessage /自定义类型 一.Void void申明方法没有返回值,执行成功后 ...

  6. c++中带返回值函数没写return能通过编译但运行时会出现奇怪问题

    c++中带返回值函数没写return能通过编译但运行时会出现奇怪问题 例如: string myFunc(){ theLogics(); } 发现调用: myFunc(); 崩溃. 但调用: cout ...

  7. try--catch--finally中return返回值执行的顺序(区别)

    1.try块中没有抛出异常,try.catch和finally块中都有return语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static int ...

  8. javascript学习笔记-2:jQuery中$("xx")返回值探究

    最近在写一个jQuery插件的时候,需要用到一个条件: 一组img标签,每一个元素都需要被它前面的元素值src替换,如果是第一个(序列为0)则其值为最后一个元素值,如果是最后一个,那么其值为第一个元素 ...

  9. try--catch--finally中return返回值执行的顺序

    1.try块中没有抛出异常,try.catch和finally块中都有return语句 public static int NoException(){ int i=10; try{ System.o ...

随机推荐

  1. SVN在团队项目中的使用技巧:[2]Tag操作

    SVN是Subversion的简称,是一个开放源代码的版本控制系统 本节讲述SVN使用中的TAG操作 文中若有错误或不足之处,欢迎留言指正   工具/原料 电脑 SVN 方法/步骤 1.认识SVN中T ...

  2. Redis容量及使用规划(转)

    在使用Redis过程中,我们发现了不少Redis不同于Memcached,也不同于MySQL的特征. (本文主要讨论Redis未启用VM支持情况) 1. Schema MySQL: 需事先设计Memc ...

  3. QRCode.jar生成二维码

    参考http://www.oschina.net/code/snippet_2252392_45457 package com.ORcode; import java.awt.image.Buffer ...

  4. SQL语句的Select部分只写必要的列

    如果Select部分包含不需要的列,这会强制DB2必须进入数据页来得到所请求的特定列,这就要求更多的I/O操作.另外,如果再对这个不需要的列进行排序,就需要创建和传递一个更大的排序文件,相应地会使排序 ...

  5. 转-Android 之 使用File类在SD卡中读取数据文件

    如果需要在程序中使用sdcard进行数据的存储,那么需要在AndroidMainfset.xml文件中 进行权限的配置: Java代码:   <!-- 在sd中创建和删除文件的权限 --> ...

  6. 启动httpd服务:SSLCertificateFile: file '/var/www/miq/vmdb/certs/server.cer' does not exist or is empty

    启动httpd服务,失败: [root@test vmdb]# service httpd restart Stopping httpd: [FAILED] Starting httpd: Synta ...

  7. 读取缓存模拟----FIFO

    本例是模拟缓存的存储和读取. 存储:使用一个Map来存放,key是文件名,值为缓存对象 读取:返回相应的key对应的缓存.(如果缓存被修改,就重新加载缓存,再从缓存Map中读取相应缓存) 测试类:每2 ...

  8. Eclipse自动补全功能和自动生成作者、日期注释等功能设置

    修改作者.日期注释格式:打开Windows->Preferences->Java->Code Style->Code Templates,点击右边窗口中的Comments,可以 ...

  9. Java SE 第十讲---面向对象特征之封装2

    1.类中的属性又叫做成员变量(member variable),属性用英文表示为property或者attitude 2.对象(Object)又叫做实例(Instance),生成一个对象的过程又叫做类 ...

  10. oracle客户端精简绿色版-环境变量配置

    大型项目开发中,常用的数据库,当属Oracle.但Oracle 客户端安装就要一张光盘,体积很大.而且安装后,基本上就用2个功能:TNS配置服务名,SqlPlus.在开发过程中,大量使用Toad和PL ...