转载请注明出处:https://www.cnblogs.com/kelamoyujuzhen/p/9427555.html

pass by value vs. pass by reference (to const)

pass by value是整包传递,不管这个包多大。传的动作实际上是压到funtion stack memory中。stack memory中有个好处就是Automatic memory management and garbage collection,但是整包传递的做法实在不高明。C为了解决整包传递效率低下问题引入pointer,不传递整包东西而是改为传递整包东西的地址,32为架构下一个pointer只占4Byte,速度很快。C++引入reference,其行为像pointer,但是处理手段更漂亮更高明。不像指针,你可以把指针的地址打印出来,reference让人看不到摸不着。reference在底部就是一个pointer,pass by reference就相当于pass by pointer那么的快。虽然你可能遇到传单个字符(大小才1Byte),这种情况下pass by value比pass by reference还快,但大多数情况,或者一个通用的准者是首选pass by reference.

C中pass by pointer,接收者对pointer的更改会影响发送者。C++中pass by reference 也会存在这个问题。如果你不希望接收者修改reference,你可以加上const限定。

return by value vs. return by reference (to const)

C++ reference主要用途就是传递 ,可以传递参数,也可以传递返回值。

在函数需要return的时候,优先选择return by reference。但是能不能return by reference还要视情况而定。如果你要return的那个东西,事先已经存在过,也就是说已经有一块memory可以存放这个东西,那么OK,你可以return by reference,速度很快。如果事先没有memory接收这个东西,那么你就只能传回一个local object。有些经验老道的程序员还会借助C++中 typename(...)这个特殊语法,返回tmp object加快程序执行效率,这种tmp object的生存周期很短,只有一行代码。无论是local object还是tmp object,你都不能return by reference。因为一旦出了function,你reference的那块memory就被回收了。严格意义上说被回收的那段memory是function stack memeory。

补充:tmp object

Null reference

C++不允许出现Null reference

个人观点:C/C++声明一个变量,声明是不赋值的,属于弱符号。对于一个不赋值的弱符号而言,如果是全局变量则在编译阶段放在.bss节,;如果是局部变量,也就是auto类型,是在程序运行期间自动分布于栈内存。总之是没有开辟内存空间。引用本质上是对一段已经命名的内存空间起个别名。所以对于空引用而言,他就不可能引用一段不存在的内存。C++引用着这种做法和Python很像,Python通过分析一段内存的引用计数来决定是否回收这段内存。当然,C++不会自动帮我们回收内存,处理好内存是一个程序员的基本素养。

传递者无需知道接收者以reference形式接收

想想C在函数中return by pointer的场景

returnType *functionName(param list);

__doapl(...)左边参数是一个pointer,返回值是*ths,是pointer指向的一个东西,也就是object,是value。这里体现了reference的好处,接收者此案例中是使用reference接收,当然你使用return by value,也就是包传递也完全OK,只是效率上没有return by reference快。C++也可以像C一样return by pointer,但是传递着必须做出更改,也就是所传递的形式看起来是pointer。

注意体会这种思想,reference作用的场景是涉及到传递的时候,无论是参数传递还是函数返回值传递。

上图中operator+=返回值是complex& ,其实完全可以返回void。因为+=执行完其结果已经放到this里面了。这样的确可以,应对c2 += c1完全没问题。

但是返回void的情形无法应对连续使用+=的情况,例如c3 += c2 += c1,c2 += c1返回值时void,c3 在调用+=的时候就不符合定义了。返回complex&就可以。

reference使用场景

对普通变量的引用

#include<iostream>

int main(int argc, char **argv)
{
int a = ;
int &b = a;
getchar();
return ;
}

引用b  和 a指向同一块内存

对指针的引用

 #include<iostream>

 int main(int argc, char **argv)
{
int a = ;
int *p = &a;
int* &q = p;
getchar();
return ;
}

对数组引用

 #include<iostream>

 int main(int argc, char **argv)
{
int ar[];
int(&br)[] = ar;
getchar();
return ;
}

讨论对常量的引用

#include<iostream>

int main(int argc, char **argv)
{
const int a=;
int &b = a;
getchar();
return ;
}

这个代码在VS 2017下编译不过。a是个常量(使用const限定),b是个引用,但是b没有加const限定,他引用a,会有一种嫌疑,即b可以间接修改a,导致a不再是常量。所以要想引用常量a,必须使用常引用,代码如下

#include<iostream>

int main(int argc, char **argv)
{
const int a=;
const int &b = a;
getchar();
return ;
}

像这种引用也是可以的

 #include<iostream>

 int main(int argc, char **argv)
{
int a=;
const int &b = a;
getchar();
return ;
}

跨数据类型的引用

分析如下代码,这里的引用比较怪异。引用 和 被引用指向的内存不一样,这是因为引用了临时对象的内存。

 #include<iostream>

 int main(int argc, char **argv)
{
double a=3.14;
const int &b = a;
getchar();
return ;
}

发现b 和 a并没有指向同一块内存。这是因为开辟了临时整形,b引用的是临时整形。这种引用会有潜在风险,万一被引用的临时变量被释放掉(超过作用域),b就引用了一个不存在的东西,程序崩溃。

如下2段代码也是编译不过的

代码1

 #include<iostream>

 int main(int argc, char **argv)
{
const double a=3.14;
int &b = a;
getchar();
return ;
}

代码2

 #include<iostream>

 int main(int argc, char **argv)
{
double a=3.14;
int &b = a;
getchar();
return ;
}

原因:临时变量都是具有常量性质的,你不能使用一个变量去引用常量,这样有潜在改变常量的风险

代码1对应改成

 #include<iostream>

 int main(int argc, char **argv)
{
const double a=3.14;
const int &b = a;
getchar();
return ;
}

代码2对应改成

 #include<iostream>

 int main(int argc, char **argv)
{
double a=3.14;
const int &b = a;
getchar();
return ;
}

就没问题了。

C++——引用 reference的更多相关文章

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

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

  2. 条款21:必须返回对象object时,不要返回其引用reference

    如下为一个有理数类,其中包含一个用来计算乘积的函数: #include <iostream> using namespace std; class Rational { public: R ...

  3. jvm内存JVM学习笔记-引用(Reference)机制

    在写这篇文章之前,xxx已经写过了几篇关于改jvm内存主题的文章,想要了解的朋友可以去翻一下之前的文章 如果你还不了解JVM的基本概念和内存划分,请阅读JVM学习笔记-基础知识和JVM学习笔记-内存处 ...

  4. 引用reference作用域scope闭包closure上下文context用法

    引用(reference).作用域(scope).闭包(closure)以及上下文(context)是JavaScript重中之重的基础,也是学习好JavaScript的基础.在这里我以浅显的理解给大 ...

  5. c++基础之引用reference

    1.何为引用 简单来说就是,比如你换了个新名字,用新名字叫你,你也会答应 2.引用vs指针 -引用没有null,好比你说你换了个新名字,但是新名字是啥总得有点东西 -一旦引用被初始化后就不可以指到另外 ...

  6. 引用 Reference

    在Java中,判断一个对象是否 "存活" ,都和引用有关,当一个对象没有任何的引用指向它,我们可以认为这个对象可以被GC了. 引用如何定义?Object obj = new Obj ...

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

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

  8. 深入浅出C++引用(Reference)类型

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

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

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

随机推荐

  1. Java Audio : Playing PCM amplitude Array

    转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2011/12/java-audio-playing-pcm-amplitude-array.html ...

  2. ubuntu18.04安装flat-remix-gnome主题

    flat-remix-gnome主题的github地址:https://github.com/daniruiz/flat-remix-gnome ubuntu下进行如下操作: sudo add-apt ...

  3. WEUI switch 如何取值?

    let id = $(this).attr("id"); let name = $(this).attr("data-name"); HTML: <div ...

  4. vue项目开发优化

    1 按需引入ui组件 比如elementUI,不要直接在main.js中全局引入所有的组件,可以根据elementui的说明文件,按需引入 项目中的组件 2 异步引入路由组件 使用 { path:'/ ...

  5. 使用Jedis出现Connection refused的解决方案

    1.修改redis.conf配置文件中的   bind 127.0.0.1  为本机外网IP: 2. cluster-enabled yes  设置是否集群操作,如果是的话开启 yes,否的话 设置n ...

  6. Appium移动自动化测试-----(六)1.appium-desktop下载安装

    Appium 移动测试中有个很重新的组件 Appium-Server,它主要用来监听我们的移动设备(真机或模拟器),然将不同编程语言编写的 appium 测试脚本进行解析,然后,驱动移动设备来运行测试 ...

  7. linux-rsync-同步本地文件夹

    linux-rsync-同步本地文件夹 1.安装rsync: yum list rsync yum install rsync 3.使用rsync命令进行同步 rsync -av 源目录 目标目录

  8. LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15

    110. 平衡二叉树 110. Balanced Binary Tree 题目描述 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点的左右两个子树 ...

  9. Word 带圈字符 1~20 快捷键的输入的技巧

    1. 前言 如何在Word中输入带圈数字?为大家分享一种快速录入带圈字符的方法,就是使用快捷键. 2. 输入带圈字符 1.在Word中输入2465,然后使用快捷键「ALT + X」就能变成⑥:输入24 ...

  10. SQL——UPDATE(改)

    一.UPDATE语句基本用法 UPADTE语句用于修改表中已存在的记录. UPDATE语句语法: UPDATE 表名 SET 列名1 = 值1,列名2 = 值2... WHERE 条件语句; 演示st ...