返回方式

  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. python子进程模块subprocess详解与应用实例 之二

    1.2. Popen 对象 Popen类的实例有下列方法: 1. Popen.poll() 检查子进程是否已经结束,设置并返回返回码值. 2. Popen.wait() 等待子进程结束,设置并返回返回 ...

  2. Gym 101128A :Promotions (Southwestern Europe Regional Contest )

    题意 一个公司里有E个员工P个上下级关系.这个公司有一种晋升制度.如果要晋升员工a,那么必须要先晋升a的所有领导.给出一个区间[A,B],如果要晋升A个员工,有哪些员工是一定会被晋升的?如果要晋升B个 ...

  3. 图的第k短路

    [问题描述] 给你一个有向图,求从1到n的第k短路. [解法] SPFA+A*搜索. 1 A*算法 A*算法在人工智能中是一种典型的启发式搜索算法,启发中的估价是用估价函数表示的: h(n)=f(n) ...

  4. PHP数组在循环的时候修改本身的值

    这样的修改并不是修改本身,$item就相当于赋值了一份数组中的值,就跟JAVA中的值方式传递值类型一样,我只是拿了你的值,并不是拿了你的内存地址,所已$item的改变,并不会影响数组 第一种方式就是直 ...

  5. laravel 中的Gates,以及修改模型

    Gates 是一个用于判断用户是否有权进行某项操作的闭包,通常使用Gate 门面定义在 App\Providers\AuthServiceProvider类中.Gates 总是接收用户实例作为第一个参 ...

  6. Bootstrap 中的 aria-label 和 aria-labelledby 属性

    这两个属性是为特殊网页阅读器设置的属性,在一些特殊设备上,当浏览到这样的内容设备会将内容读出来.是为了一些有视力障碍的人能够同样”浏览”网页而准备的. 转自http://blog.csdn.net/l ...

  7. sublime text 3安装 vue插件

    1.上一个章节讲到Vue.js的环境安装,这一章节主要是针对ST3 如何安装vue插件,来快速的进行vue组件代码的编写. (内容转载自:https://www.cnblogs.com/bluedoc ...

  8. 安全、结构良好的jQuery结构模板

    安全.结构良好的jQuery结构模板 ;(function($,window,document,undefined){ //我们的代码- })(jQuery,window,document);   参 ...

  9. C# 随机数 Radom 循环生成同一的数字

    错误:在一个循环结构中,利用下列代码生成随机数,发生生成的随机数是一样的! for (int i = 0; i < myArray.Length; i++) //给数组赋值 { Random m ...

  10. DataTable与结构不同实体类之间的转换

    在实际开发过程中,或者是第三方公司提供的数据表结构,与我们系统中的实体类字段不对应,遇到这样我们怎么处理呢?可能有人会说,在转换时创建一个实体对象,对表里的数据逐行遍历来实例化这个实体对象不就完了.的 ...