返回方式

  1. 返回指向对象的引用;
  2. 指向对象的const引用;
  3. const对象;

 ===============================================

返回指向const对象的引用

假如要编写函数Max(),它返回两个Vector对象中较大的一个,其中Vector是第11章开发的一个类。

Vector force1(50, 60);

Vector force2(10,70);

Vector max;

max = Max(force1, force2);

//version 1

Vector Max(const Vector & v1, const Vector & v2)

{

if (v1.magval() > v2.magval())

return v1;

else

return v2;

}

//version 2

const Vector & Max(const Vector & v1, const Vector & v2)

{

if (v1.magval() > v2.magval())

return v1;

else

return v2;

}

返回对象将调用复制构造函数,而返回引用不会。因此第二个版本所做的工作更少,效率更高。引用指向的对象应该在调用函数执行时同时存在。

注意v1和v2被声明为const引用,所以返回类型必须为const,这样才匹配。

=============================================

返回指向非const对象的引用

Operator=()的返回值作用域连续赋值

String s1(“Good stuff”);

String s2,s3;

s3=s2=s1;

上述代码中,s2.operator=()的返回值被赋给s3。为此,返回String对象或String对象的引用都是可行的。

Operator<<()的返回值用于串接输出

String s1(“Good stuff”);

cout << s1 << “is coming!”;

operator<<(cout,s1)的返回值成员一个用于显示字符串“is coming!”的对象。返回类型必须是ostream &,而不能仅仅是ostream。如果使用返回类型ostream,将要求调用ostream类的赋值构造函数,而ostream没有公有的赋值构造函数。幸运的是,返回一个指向cout的引用不会带来任何问题,因为cout已经在调用函数的作用域内。

=================================

返回对象

如果被返回的对象是被调用函数的局部变量,则不应该按引用方式去返回它,因为在被调用函数执行完毕时,局部对象将调用析构函数。因此,当控制权回到调用函数时,引用指向的对象将不再存在。在这种情况下,应返回对象而不是引用。

通常,被重载的算术运算符属于这一类。

Vector force1();

Vector force2();

Vector net;

net = force1+force2;

返回的不是force1,也不是force2,force1和force2在这个过程中应该保持不变。因此,返回值不能是指向在调用函数中已存在的对象的引用。相反,在Vector::operator+()中计算得到的两个矢量和被存储在一个新的临时对象中,该函数也不应返回指向该临时对象的引用,而应该返回实际的Vector对象,而不是引用。

在这种情况下,存在调用复制构造函数来创建被返回的对象的开销,然而这时无法避免的。

Vector Vector::operator+(const Vector & b) const

{

Return Vector(x+b.x, y+b.y)

};

========================================

返回const对象

前面的Vector::operator+()的定义中有一个奇异的属性,

net = force1 +force2; //语句1

force1 +force2 =net; //语句2

这种代码都可行,是因为复制构造函数将创建一个临时对象来表示返回值。因此,在前面的代码中,表达式force1+force2的结果为一个临时对象。在语句1中,该临时对象被赋给一个net;在语句2中,net被赋给该临时对象。

如果您担心这种行为引发滥用。有个简单的解决方案,就是把返回类型声明为const Vector。那么语句2就非法了,因为返回对象无法被赋值,只能赋值给别人。

总是,如果方法或函数要返回局部对象,就必须要返回对象,而不是返回对象的引用。这种情况下将使用赋值构造函数来生成返回的对象。这样的开销是不可避免的,也是必须的。

如果方法或函数要返回一个没有公有复制构造函数的类(例如ostream类)的对象,它必须返回一个指向这种对象的引用。[ZJ2]

最后,有些方法和函数可以返回对象,也可以返回指向对象的引用,在这种情况下,应首选引用,因为其效率更高。


不能返回局部对象的引用。很危险,因为局部对象会过期,引用会失效。

C++_类和动态内存分配4-有关返回对象的说明的更多相关文章

  1. C++_类和动态内存分配5-使用指向对象的指针

    再探new和delete new为创建的每一个对象的名称字符串分配存储空间,这是在构造函数中进行的: 析构函数使用delete来释放这些内存. 字符串是一个字符数组,所以析构函数使用的是带中括号的de ...

  2. C++_类和动态内存分配3-构造函数中使用new的注意事项

    如果在构造函数中使用new来初始化对象的指针成员时必须特别小心. 1 如果在构造函数中使用new来初始化指针成员,则应在析构函数中使用delete. 2 new和delete必须相互兼容.new对应于 ...

  3. C++_类和动态内存分配6-复习各种技术及队列模拟

    知识点: 队列:是一种抽象的数据类型(Abstract Data Type),可以存储有序的项目序列. 新项目被添加在队尾,并可以删除队首的项目.队列有些像栈.栈是在同一端进行添加和删除.这使得栈是一 ...

  4. C++_类和动态内存分配1—动态内存和类

    静态类成员 num_strings成员声明为静态存储类.静态类成员有一个特点:无论创建了多少对象,程序都只创建一个静态类变量副本.也就是说,类的所有对象共享一个静态成员.num_strings成员可以 ...

  5. C++_类和动态内存分配2-改进后的String类

    添加前面介绍过的复制构造函数和赋值运算符,使类能够正确管理类对象使用的内存. 知道对象何时被创建和释放. =================================== 修订后的默认构造函数 ...

  6. 《C++ Primer Plus》读书笔记之十—类和动态内存分配

    第12章 类和动态内存分配 1.不能在类声明中初始化静态成员变量,这是因为声明描述了如何分配内存,但并不分配内存.可以在类声明之外使用单独的语句进行初始化,这是因为静态类成员是单独存储的,而不是对象的 ...

  7. C++ primer plus读书笔记——第12章 类和动态内存分配

    第12章 类和动态内存分配 1. 静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域运算符来指出静态成员所属的类.但如果静态成员是整形或枚举型const,则可以在类声明中初始化 ...

  8. C++——类和动态内存分配

    一.动态内存和类 1.静态类成员 (1)静态类成员的特点 无论创建多少对象,程序都只创建一个静态类变量副本.也就是说,类的所有对象都共享同一个静态成员. (2)初始化静态成员变量 1)不能在类声明中初 ...

  9. C++拾遗(十)类与动态内存分配(2)

    静态成员函数 声明时包含关键字static.注意以下两点: 1.使用静态成员函数时不能通过对象或者this指针来调用,只能使用类名+作用域解析符来调用. 2.静态成员函数只能使用静态成员. new操作 ...

随机推荐

  1. 算法描述》关于LIS的nlogn方法

    上次TYVJ有一道裸LIS,然而我当时直接打了一个N^2暴力就草草了事,然后就ZZ了,只拿了60分,其实NlogN的LIS和N^2的差的不多,只是没有N^2,好想罢了,鉴于某学弟的要求,所以就重现一下 ...

  2. SpringBoot18 Swagger、API接口文档生成、WireMock、模拟后台数据

    1 Swagger 1.1 简述 前后端分离的项目需要前后端开发人员协同工作,后台开发人员需要给到前端开发者一套API文档:利用Swagger可以简单高效的帮助后台开发者生成RestfulAPI开发文 ...

  3. 通明讲JDBC(一)–认识JDBC

    本章记录了jdbc的简单使用方式! 0,jdbc的作用 1,jdbc入门准备工作 2,jdbc注册驱动 3,使用jdbc对数据库CRUD 0,jdbc的作用 与数据库建立连接.发送操作数据库的语句并处 ...

  4. c语言实践输出某个区间中不是3的倍数的偶数

    OK,先审题,我们最后要输出的那些数是需要满足两个条件的,第一个条件是,这个数不是3的倍数,第二个条件是这个数是偶数.也就是这样的数需要同时满足这两个条件的时候才把这个数输出. 不是3的倍数这个条件在 ...

  5. Openssl genpkey命令

    一.简介 genpkey命令用于产生各种密钥(RSA.DSA.DH.EC等)的私钥值. 二.语法 openssl genpkey [-out filename] [-outform PEM | DER ...

  6. Django--form保存用户输入内容

    需求 用户提交form时,如果报错,页面中的用户信息还在(除了密码),没有被刷新掉,不用用户再次输入. 速查 views.py 1 2 3 def login(request):     obj = ...

  7. 24、Linux 多线程压缩工具pigz 的学习

    转载: https://blog.csdn.net/q871761987/article/details/72230355 https://blog.csdn.net/woodcorpse/artic ...

  8. sencha表单入门例子

    来自于<sencha touch 权威指南> ------------------------------- 一.网站结构 二.index.html代码 <!DOCTYPE HTML ...

  9. Vue.js如何搭建本地dev server和json-server 模拟请求服务器

    前言:vue-cli(版本更新),由原来的2.8.1升级为2.9.1.主要改变是原来在build文件夹下的dev-server.js删掉了,增加了webpack.dev.conf.js. 所以这次讲的 ...

  10. [存储过程]中的事务(rollback)回滚

    在编写SQL Server 事务相关的存储过程代码时,经常看到下面这样的写法: begin tran update statement 1 ... update statement 2 ... del ...