惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

GeekPlux

一代人的博客,一代人的青春注脚 那些年我打过的日结工 来美国的两年后 2023 一蓑烟雨 在美国拥有一辆 Tesla 的成本 我的 Workspaces 十年进化史 How to Sync Logseq Plugins, Themes and Settings Across Multiple Devices Setting Up Umami as Your Google Analytics Alternative: A Step-by-Step Guide 迁移豆瓣读书记录到 goodreads Enhance Your Internet Privacy in 2023 Refactor your blog comments system with Webmention.io 来美国之后,如何快速安顿下来 Three Levels of Information Perception 疫情三年 与人聊天的美好 我获取信息的方法 2022 版 我是如何学会编程的 Legacy code best practice: how to take over an existing project smoothly 2020 恍如隔世 接外包的一些坑和小技巧 论交友 往返香港隔离指南 即将失明,还能继续做程序员吗 小谈我对新技术的态度 How to use tailwindcss with AMP in a Next.js project 远程工作如何提高效率 复式记账、财报、量化与图论 我为什么从阿里巴巴离职 2019 柳暗花明 YouTube 观看历史数据分析 投资被动型指数基金正在造成下一次金融泡沫? 三种主流的网赚套利,躺着赚钱? 色盲的世界 我是如何管理 21 张信用卡的 薅羊毛的最大意义:保持对规则的敏感度 来香港的两个月 数据可视化技术实现的关键点 不需要扫描仪,数字化归档自己的文件 如何找到时薪 80 美元的远程工作(二) 如何找到时薪 80 美元的远程工作(一) 如何打造真正的简历 浅思图数据可视化 舍本逐末的学习方式 给想转行作程序员的人泼一盆冷水 算法优化人生之 —— 调度算法 杭州最适合闲来溜达的几条路线 2018 平淡无奇 突闻金庸先生逝世有感 十年博客折腾历史 数据可视化之 Sankey 桑基图的实现 研究生生涯总结 如何在不规则多边形内均匀撒点的算法 Web 前端中的增强现实(AR)开发技术 参加 Google Summer of Code 的体验 netjsongraph.js – Google Summer of Code (GSoC) 2017 summary 如何在 GitHub 上获得数百 stars Markvis - 在 markdown 中生成可视化图表 D3 force layout and WebGL integration 文本数据可视化(下)——一图胜千言 文本数据可视化(上)——从 Wordle 谈起 我获取信息的渠道 数据可视化基础——视觉编码 数据可视化基础——数据模型 数据可视化基础——可视化流程 为什么要用 Emacs Vega-Lite: A Grammar of Interactive Graphics 如何搭建一个私人网盘 如何阅读一篇学术论文 超过十个人的微信群根本没有价值 毕业后的两年 建立索引式的学习方法 为什么我喜欢写代码 写文章的小技巧 为什么文章写得好的人都很厉害 人总要有点盲目的自信 如何管理好自己的密码 Backbone View 之间通信的三种方式 Vim - 适合自己的,才是最好的 轻松玩转 Ukulele 告别社交网络有多难 双拼学习记 CoffeeScript 编码风格指南(译) CoffeeScript 笔记 CSS 最核心的几个概念 响应式设计简易指南(译) 初识 TDD Collapsing margins——合并的外边距 菜鸟级 Mac 配置(二) 菜鸟级 Mac 配置(一) CSS 编写原则 Goodbye,我的大学 如何新建一个 Cocos2d-x 项目 Windows8.1 下 Cocos2d-x 环境搭建 Android 开发如何入门 如何绑定独立域名 写博客就用 FarBox 尝试改变微信公众账号消息的推送方式 情似流水 操作系统总结——存储器管理 操作系统总结——处理机管理
C++指针与引用小结
GeekPlux · 2013-01-02 · via GeekPlux

概念

引用

引用就是某一对象(变量)的一个别名。举个例子更容易理解:

int m;
int &n = m;

这段程序中,nm的一个引用(reference),m是被引用物(referent)。 n相当于m别名(绰号),对n的任何操作就是对m的操作。 n既不是m的拷贝,也不是指向m的指针,其实n就是m它自己。

指针

指针用于指向对象(变量)。指针提供对其所指对象的间接访问。指针用于指向单个对象。

(这三句摘自《C++ Primer, Fourth Edition》)。再举个例子:

int m;
int *n = &m;

第二条语句定义了一个指向int型的指针n,并初始化n使其指向int型的变量m*n中的 * 操作符表明n是一个指针变量(n本质上也是一个变量,只不过这个变量的存储内容是 地址)。 &m中的 & 符号是取地址操作符,当此操作符用于一个对象上时,返回的是该对象的存储地址。

联系

  • 都是有关地址的概念。 指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
  • 都是间接访问其他对象。
  • 都能用于函数参数和返回值的传递。

区别

  • 一、指针是一个实体(本质上就是存放变量地址的一个变量),而引用只是个别名。

这句话从内存分配的角度很好理解,程序会为指针变量分配内存区域,而引用不分配内存区域。

  • 二、指针可变,引用不可变。

指针在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变。 引用在逻辑上不独立,具有依附性,所以引用必须在一开始就被初始化,而且引用一旦和某个对象绑定后就不能再改变(从一而终)。

  • 三、指针可以为空,引用不能为空。

即指针可以为 NULL,而引用必须与合法的存储单元关联。

  • 四、传递方式不同。

首先,函数参数和返回值的传递方式大概可以理解为三种:

  1. 值传递
  2. 指针传递
  3. 引用传递

先理解值传递:值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个拷贝。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

指针传递本质上值传递,只不过它所传递的是一个地址值。然后把上面那段话「翻译」一下:指针传递时,形参是一个指针变量,该变量拷贝了实参的地址值,然后作为被调函数的局部变量(传递过来的实参的地址值不会变),再然后我们可以用*操作符访问实参,从而对实参进行操作。很绕口,不如看个例子:

#include <iostream>
using namespace std;

void f(int *n)
{
  *n = 5;
}

int main()
{
  int m = 1;
  cout << m << endl;
  f(&m);
  cout << m << endl;

  return 0;
}

该程序输出结果为:1 5

在函数f中,形参n是指向int型的指针变量,拷贝了实参m的地址,作为f函数的局部变量,然后通过*n改变实参m的值。

而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址(不必通过*操作符),即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量(此时的形参其实就是实参)。再举个例子:

#include <iostream>
using namespace std;

void f(int &n)
{
  n = 5;
}

int main()
{
  int m = 1;
  cout << m << endl;
  f(m);
  cout << m << endl;

  return 0;
}

输出结果为:1 5

nf中的局部变量,同时n也是实参m的引用。此时n就为m,所以在f中对n的操作都会影响m,为n赋值 5 就是对m赋值 5。

还可以从编译角度理解(此处从网上摘录):

程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。

  • 五、引用不能 const,指针能 const,const 的指针不可变。 对于引用,具体指没有 int&const a 这种形式,而 const int& a 是有的, 前者指引用本身(即别名)不可以改变,这是理所当然的,所以不需要这种形式,后者指引用所指的值不可以改变)

  • 六、「sizeof 引用」得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小。

  • 七、指针和引用的自增(++)运算意义不一样(很好理解)。

要理解知识必须先建立知识的结构,就像盖楼房一样,必须先有框架,所以此处附上本人制作的一幅简单的思维导图: