要点1:为反复使用的冗长的变量名称定义一个简短的、易用的别名,从而简化了代码。通常,冗长的变量名称源于多层嵌套对象,例如类中定义嵌套类,类中定义其它类对象。

//------ 未使用引用的程序片段,反复使用的、冗长的变量名称,极易书写出错 ------

Computer.Host.Cpu.enBrand = enIntel;

Computer.Host.Cpu.TypeName = "Core Duo 2 E7400";

Computer.Host.Cpu.CoreNum = 2;

Computer.Host.Cpu.FrequencyInGhz = 2.8.;

//------ 使用了引用的程序片段 ---------------------------------------------------------------------

// 如果编译器支持C++11标准,以简练方式定义引用变量

auto &rCpu = Computer.Host.Cpu;

// 如果编译器不支持C++11标准,以标准方式定义引用变量

TComputer::THost::TCpu &rCpu = Computer.Host.Cpu;

// 使用引用,极大地简化代码,减少了书写出错

rCpu.enBrand = enIntel;

rCpu.TypeName = "Core Duo 2 E7400";

rCpu.CoreNum = 2;

rCpu.FrequencyInGhz = 2.8.;

要点2:const引用类型作为函数参数,拓宽了函数入口参数的接受范围,极大地增加了程序的灵活性和适应性。

// 声明函数原型如下:

void ShowMsg(UnicodeString &s);

// 调用函数ShowMsg(),入口参数不是UnicodeString类型,编译立即报错

ShowMsg(10); // 不是UnicodeString类型

ShowMsg(3.1415926); // 非法,3.1415926不是UnicodeString类型

ShowMsg("This is C-style string.") // 非法,"This is C-style string."不是UnicodeString类型

// 将函数原型修改为:

void ShowMsg(const UnicodeString &s);

// 调用函数ShowMsg(),入口参数可以是能够转换为UnicodeString类型的任意数据类型

ShowMsg (10); // 不是UnicodeString类型

ShowMsg (3.1415926); // 合法,虽然3.1415926不是UnicodeString类型

ShowMsg ("This is C-style string.") // 合法,虽然"This is C-style string."不是UnicodeString类型

const关键字产生了很神奇的效果吧? 想知道为什么吗? 内在的工作机理是:

S1:在函数func()的原型中,如果未将入口参数声明为const类型的引用,说明该函数有意修改该入口参数对象的值,入口参数必须是所声明的数据类型,且必须是存在于被调用函数之外的可寻址、可修改(写入)对象。

S2:在函数func()原型中,如果将类型为T的入口参数声明为const类型的引用,说明该函数无意修改该入口参数对象的值,就可以接受能够转换为类型T的任意数据类型,这些数据类型称为可转换类型。

QQQ 什么是可转换类型 ???没你想得那么简单!

定义:对于数据类型T,存在一个构造函数,其唯一入口参数是数据类型K,就称K可转换为T。这个构造函数称为可转换构造函数T(K)。

QQQ 处理函数调用语句时,编译器如何识别给定的实际参数是可转换类型 ???

QQQ 如果编译器找到可转换构造函数,又将如何进行编译处理呢 ???

S1:如果函数func()的入口参数要求数据类型const T&, 而程序给定的实际参数的数据类型是K,在处理函数调用语句时,编译器搜索可转换构造函数T(K),若没有找到该函数,编译报错。

S2:若找到可转换构造函数T(K),编译器就会调用该构造函数生成一个数据类型为T的临时对象,记作t(k),并将t(k)作为实际参数传递给func,形成实际调用func(t(k))。

哇哈哈!!!原来函数func()得到的实际参数的数据类型总是为T。

哇哈哈!!!函数func()之所以看起来能够接受多种类型的实际参数,是因为编译器在其中做了许多工作。

QQQ 临时对象t(k)的生命周期是多长 ???

AAA:在函数func()执行完毕后,临时对象t(k)被自动释放。

重温上面的范例函数:

// 将函数原型修改为:

void ShowMsg(const UnicodeString &s);

// 调用函数ShowMsg(),入口参数可以是能够转换为UnicodeString类型的任意数据类型

ShowMsg (10); // 合法,int类型→UnicodeString类型

ShowMsg (3.1415926); // 合法,double类型→UnicodeString类型

ShowMsg ("This is C-style string.") // 合法,const char *类型→UnicodeString类型

来看看UnicodeString的构造函数:

// UnicodeString的构造函数,好大一堆呢,可转换类型真不少 !!!

__fastcall UnicodeString(): Data(0) {}

__fastcall UnicodeString(const char* src);

__fastcall UnicodeString(const UnicodeString& src);

__fastcall UnicodeString(const wchar_t* src, int len);

__fastcall UnicodeString(const char* src, int len);

__fastcall UnicodeString(const wchar_t* src);

__fastcall UnicodeString(const char16_t* src, int numChar16 = -1);

__fastcall UnicodeString(const char32_t* src, int numChar32 = -1);

__fastcall UnicodeString(char src): Data(0) { sprintf(L"%c", src);}

__fastcall UnicodeString(wchar_t src): Data(0) { SetLength(1)[1] = src; }

__fastcall UnicodeString(short src): Data(0) { sprintf(L"%hd", src); }

__fastcall UnicodeString(unsigned short src): Data(0) { sprintf(L"%hu", src); }

__fastcall UnicodeString(int src): Data(0) { sprintf(L"%i", src); }

__fastcall UnicodeString(unsigned int src): Data(0) { sprintf(L"%u", src); }

__fastcall UnicodeString(long src): Data(0) { sprintf(L"%ld", src); }

__fastcall UnicodeString(unsigned long src): Data(0) { sprintf(L"%lu", src); }

__fastcall UnicodeString(__int64 src): Data(0) { sprintf(L"%Li", src); }

__fastcall UnicodeString(unsigned __int64 src): Data(0) { sprintf(L"%Lu", src); }

__fastcall UnicodeString(double src);

__fastcall UnicodeString(const WideString &src);

QQQ 是否发现了函数ShowMsg()用到的可转换构造函数 ???

QQQ 函数ShowMsg()还可以接受哪些数据类型作为入口参数 ???

!!! 千万注意 !!!

既然将入口参数声明为const T&类型, 函数就不可以修改该参数对象,否则编译报错 !

要点3:引用就好像是皇帝的驸马,一次迎娶永远无法解除婚约。

// 声明或定义一个引用对象时,就好像说"独孤谋是李世民的驸马",因为驸马不可以是单身,不可以不指定公主和皇帝

// 声明或定义一个引用对象时,必须初始化,指定是哪个变量的别名:

// 使用 auto关键字声明引用对象,编译器必须支持C++11标准

auto &rCpu; // 错误,未指定作为哪个变量的别名

auto &rCpu = Computer.Host.Cpu; // 正确,指定了别名对象

// 声明(定义)之后,无法再次指定作为其它变量的别名,因为驸马是不可以离婚的

TComputer::THost::TCpu Amd = {enAMD, "A6300", 4, 2.2};

// 此句的意思是把Amd的值赋给rCpu的实际对象Computer.Host.Cpu,而不是作为Amd的别名。

rCpu = Amd;

要点4:以引用类型作为函数入口参数:

S1:参数传递时与指针相同,传递的是对象地址,提高了程序效率;

S2:在被调用函数内部使用入口参数与使用普通变量完全相同,方便易用

以引用类型作为函数入口参数

以指针类型作为函数入口参数

void ShowComputerInf(TComputer &Computer)

{

// 入口参数的用法与使用普通变量完全相同

ostringstream oss;

oss << Computer.Brand << endl;

oss << Computer.TypeId << endl;

oss << Computer.Price << endl;

}

void ShowComputerInf(TComputer *Computer)

{

// 入口参数必须按指针方式使用

ostringstream oss;

oss << Computer->Brand << endl;

oss << Computer->TypeId << endl;

oss << Computer->Price << endl;

}

int main(void)

{

TComputer Computer;

// 数据初始化…

// 调用函数,使用对象名称传递对象地址,易用

ShowComputerInf(Computer);

return 0;

}

int main(void)

{

TComputer Computer;

// 数据初始化…

// 调用函数,传递对象地址必须带"&",易出错

ShowComputerInf(&Computer);

return 0;

}

深入浅出C++引用(Reference)类型的更多相关文章

  1. 再论C++引用(reference)类型

    很多C++初学者搞不清楚C++引用类型,不知有什么用,所以也不知怎么用.一个问题令人迷惑,不是读者有问题,而是教科书有问题. 和多数初学者一样,笔者在初学C++时,关于引用类型,教科书上也是如下表所述 ...

  2. 【JavaScript】从 this 指向到 reference 类型

    判断"this 指向谁"是个老大难的问题. 网络上有许多文章教我们如何判别,但大多艰涩复杂,难以理解. 那么这里介绍一个非常简单实用的判别规则: 1)在函数[调用]时," ...

  3. Lambda语言篇 —— lambda, 方法引用, 目标类型和默认方法

    本文介绍了Java SE 8中新引入的lambda语言特性以及这些特性背后的设计思想.这些特性包括: lambda表达式(又被成为"闭包"或"匿名方法") 方法 ...

  4. 浅谈String中的==和对象中引用对象类型的==

    @Test public void test02() { StringBuffer sb = new StringBuffer(); sb.append('a'); sb.append(11); Sy ...

  5. 关于java内存泄露的总结--引用的类型:强引用,弱引用,软引用

    今天面试了一家公司的java开发方面的实习生,被问到一个问题:如何处理java中的内存泄露问题,保证java的虚拟机内存不会被爆掉,当时其实觉得面试官的问题有点泛,所以也没有很好领会他的意思,答案也不 ...

  6. Object-C中对“引用(reference)”的理解

    http://blog.csdn.net/csz0102/article/details/25984275 注:以下讨论都是在ARC模式下 我们在iOS开发中最经常碰到的“引用(reference)” ...

  7. javascript原始值和引用值类型及区别

    原始值和引用值类型及区别 首先,原始值和引用值类型都是js中的数据类型,为了充分利用存储空间,定义了不同的数据类型,而且js是弱类型,动态语言,数据类型可变. 原始值(简单数据类型) 存储在栈中的简单 ...

  8. Java中各种引用(Reference)解析

    目录 1,引用类型 2, FinalReference 2.1, Finalizer 3, SoftReference 4, WeakReference 5, PhantomReference 6, ...

  9. C++——引用 reference

    转载请注明出处:https://www.cnblogs.com/kelamoyujuzhen/p/9427555.html pass by value vs. pass by reference (t ...

随机推荐

  1. ASP.NET缓存全解析6:数据库缓存依赖 转自网络原文作者李天平

    更多的时候,我们的服务器性能损耗还是在查询数据库的时候,所以对数据库的缓存还是显得特别重要,上面几种方式都可以实现部分数据缓存功能.但问题是我们的数据有时候是在变化的,这样用户可能在缓存期间查询的数据 ...

  2. C语言中关于float和double的输入输出格式

    1.对于double类型,输入格式为scanf("%lf %lf", &foo, &bar); 对于float类型,输入格式为scanf("%f %f, ...

  3. NSTimer实现读秒、倒计时等周期性操作

    self.timerSchedule = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(spin ...

  4. Ajax的ActionLink方法(适用于异步加载)

    8.2.1  AJAX的ActionLink方法 在Razor视图中,AJAX辅助方法可以通过Ajax属性访问.和HTML辅助方法类似,Ajax属性上的大部分AJAX辅助方法都是扩展方法(除了Ajax ...

  5. 理解C#系列 / 核心C# / 变量

    变量 变量? 变量是对一个东西指定一个名称,变量的功能和人的名字差不多,提到名字就知道指的是什么. 变量类型? 变量类型说明了变量的类型,声明变量是一个整数,还是小数,还是字符,或是图像,或是人类,或 ...

  6. c#实现数据集合转换为csv文本

    需求 1.将一个数据集合导出到一个csv文件中,集合类型可以视为 List<T>,T为任意类型,T包含多个属性,可指定部分属性进行导出 2.软件中有多种不同类型的数据类型需要进行导出 需求 ...

  7. oc - runtime运行机制

      Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时做的事放到了运行时来处理.同时OC也是一门简单的语言,很大一部分是C的内容,只是在语言层面上加了关键字和语法,真正让OC强大 ...

  8. IOS,发短信,发邮件,打电话

    今天把APP里常用小功能 例如发短信.发邮件.打电话.全部拿出来简单说说它们的实现思路. 1.发短信实现打电话的功能,主要二种方法,下面我就分别说说它们的优缺点.1.1.发短信(1)——URL // ...

  9. 游戏对象的变换-Transform

    问题: 在给GameObject设置位置的时候,怎么保证设置的位置在摄像机的范围内?         主要看摄像机的深度轴和你的GameObject的深度轴,比如如果现在的平面是: Z–> Y, ...

  10. 【Qt】Qt Creator介绍【转】

    简介 Qt Creator是使用Qt开发的IDE.Qt支持Windows.Linux/Unix.Mac OS X.Android.BlackBerry.QNX等多种平台,Qt Creator为不同平台 ...