菜鸟资源网站全面焕新升级啦!全新的界面设计,简洁而不失雅致,让您一目了然,轻松上手。我们还对资源分类进行了细致梳理,确保各类资源条理清晰,便于您按需筛选与查找。 立即查看
通知图标

正在访问 第九章:引用难道只是别人的替身,了解C++基本语言特性变量和类型

第九章:引用难道只是别人的替身,了解C++基本语言特性变量和类型

第九章:引用难道只是别人的替身,了解C++基本语言特性变量和类型

  引用是我们多次讨论的概念了,引用只是默认值的别名。对引用唯一的操作就是将其初始化。一旦引用初始化结束,引用就只是其默认值的另一种写法罢了。引用变量没有地址,甚至它们可能不占用任何存储空间。   注意事项   (1) 声明引用的引用、指向...

当前版本

软件大小

软件语言

是否破解

  引用是我们多次讨论的概念了,引用只是默认值的别名。对引用唯一的操作就是将其初始化。一旦引用初始化结束,引用就只是其默认值的另一种写法罢了。引用变量没有地址,甚至它们可能不占用任何存储空间。

  注意事项

  (1) 声明引用的引用、指向引用的指针、指向引用的数组都是非法的。

  (2) 引用不可能带有常量性和挥发性,因为别名不能带有常量性和挥发性。用关键字const和volatile修饰引用会造成编译错误。

  (3) 用const或volatile修饰引用类型,不会造成编译错误,但是编译器会默认忽略这些修饰。

inta=12;
int &ra =a;
int &p =&ra;      //p指向a的地址
a=42;             //ra和a的值都变成了42
int &&rri=ra;     //错误
int&*pri;         //错误
int &ar[3];       //错误

  我们一直在说引用就是别名,既然是别名,就要是“某个已存在变量”的别名,并且这个变量必须真实存在才行。其实引用不只是简单变量名的别名,其任何可作为左值的复杂表达式都可以作为引用的默认值。只要类型确定,有明确的内存地址,可做左值,就可初始化引用。引用和函数相结合时,有如下几种功能:

  (1) 如果一个函数返回一个引用,这说明此函数的返回值可重新赋值。我们经常使用的 STL库中所有的下标操作基本上都是这样返回引用的形式。例如 vector 数据类型的下标操作声明:

template <class T, class Alloc =alloc> // vector STL模板类声明
class vector
{
public:
  typedefT
  value_type; // 数据类型
  typedef value_type  reference;
  typedef size_t       size_type;
  typedef value_type*iterator;
  ...
protected:
  iterator start;
public:
  iterator begin() { return start;}
  reference operator[] (size_type n) { return *(begin() + n);
}

  (2) 引用的另一个用途即让函数在其返回值之外多传递几个值。例如:

typedef int failure;
char *FindStr(const char *pszMainStr, failure &reason);

  (3) 另外一个需要特别注意的地方是,指向数组的引用保留了数组的长度信息,而指针不会保留数组的长度信息。例如下面的代码,Array_Test1 函数可记住实参必须为长度为 3 的数组,而Array_Test2 却无法记录,导致长度为 2 的数组也可作为实参传给函数。

//引用形式数组测试函数
void Array_Test1(int (&array)[3])
{
  array[2]=3;
}
//非引用形式数组测试函数
void Array Test2(int array[3])
{
  array[2]=3;
int _tmain(int argc, char* argv[])
{
  int n3[2]={2, 4};
  Array_Test1(n3); //错误“Array_Test1”:不能将参数1 从“int [2]”转换为“int(&)[3]”
  Array_Test2(n3);//可正常编译通过
}

  (4) 最后,我们讨论一下常量引用(const reference)。为了阐述常量引用的特殊之处,我们看下面的代码:

int &rInt=12;       //错误
constint&rInt=12;  //正常编译通过

  可以看出常量值不能给普通引用初始化,但是可以给const引用初始化。

小心陷阱

  ● 如果初始化值是一个左值(可以取得地址),则可以初始化引用,没有任何问题。

  ● 如果初始化值不是一个左值,则只能对constT&(常量引用)赋值,且赋值过程包括3个阶段:首先将值隐式转换到类型T,然后将这个转换结果存放在一个临时对象里,最后用这个临时对象来初始化这个引用变量。

  ● 在这种情况下,constT&(常量引用)过程中使用的临时对象会和constT&(常量引用)共“存亡”。

  上述代码中,引用 rInt指向编译器隐式分配内存并创建的匿名int类型临时对象。对 rInt引用的任何操作都会影响匿名临时变量,而不会影响常量 12。同时编译器也会确保这样的匿名临时对象会将生命期扩展到初始化后的引用存在的全部时域。这无形之中也开启了临时生命期问题的万劫不复之门。我们来看下面这段普通代码:

shorts=123;
const int &rIntegrate = s;
s=321;
const int *ip = &rlntegrate;
printf("rIntegrate =%d, s = %dr\n", rIntegrate, s);
printf("ip = %d, &s = %d", ip, &s);

  输出结果为:

rIntegrate = 123, s =321
ip=2030760,&s =2030784

  可看出 rIntegrate引用的默认值并不是 s,而是常量引用初始化过程中隐式使用的匿名对象。接着,我们看一下const引用作为函数形参存在的问题。来看下面这段代码:

const int&GetMax(const int &a, const int &b)
returm ((a>b)?(a): (b));

  乍一看,此函数完全无害:函数功能很简单,就是返回两个参数中的一个。引发问题的是那个 retun 语句。因为 a、b都是const引用,在函数参数实参传值时,函数首先会生成两个临时对象将实参的值复制到临时对象中,然后用这两个临时对象初始化a、b。现在你也许明白了:函数返回了临时变量的引用。

 请谨记

  ● 若非必要请不要使用const引用,因为const引用有时会伴随着临时对象的产生。

  ● 在函数声明时,请尽量避免const引用形参声明,使用非const引用形参替代,以防因返回const引用生成的临时变量而导致程序执行错误。

第九章:引用难道只是别人的替身,了解C++基本语言特性变量和类型
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

常见问题

  • 如何安装和激活?

    每款软件会附带有安装教程,您打开安装包一目了然

  • 程序是否已损坏?文件损坏?还是其他错误?

    有错误问题,请您参考:https://www.xxx.com/error

  • 如何更新?正式激活后会发生什么情况?

    除非安装说明中另有说明,否则官方更新可能会导致无法激活。 要从本网站更新软件,您需要在此处下载此软件的新版本(如果可用),并将其安装在计算机上安装的版本之上(替换)。在这种情况下,您将保存此软件的激活和设置。

  • 如何下载?链接不起作用?

    我们使用百度网盘,132云盘和微软网盘,除了百度网盘,其他两款不限速,如果链接失效,请您联系客服处理

  • 已发布更新。我什么时候升级我的版本?

    所有软件如有更新,我们第一时间推送,视自己情况更新使用

  • 如何更改语言?

    打开“系统偏好设置”->“通用>语言和地区”->应用程序-“+”。 选择应用和语言。此方法适用于大多数应用程序。 Adobe 产品中的语言通常是在产品本身的安装阶段选择的。 游戏中的语言通常会在游戏本身的设置中发生变化。

  • 如何删除软件?

    有很多选择。最简单的方法是使用特殊的实用程序来卸载应用程序,例如App Cleaner Uninstaller 要删除 Adobe 产品,请使用 Creative Cloud Cleaner Tool

  • 需要远程帮助吗?

    网站已开通永久会员的可享受免费远程,如果非永久会员,远程安装另外收费

给TA打赏
共{{data.count}}人
人已打赏
技术教程

新版宝塔的 SQL 注入漏洞

2024-2-17 12:53:52

技术教程

第十章:枚举和一组预处理的#define 有何不同,了解C++基本语言特性变量和类型

2024-2-19 10:34:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
后退
榜单