C++二级指针和指针引用传参
前提
一级指针和引用
已经清晰一级指针和引用。
可参考:指针和引用与及指针常量和常量指针 或查阅其他资料。
一级指针和二级指针
个人觉得文字描述比较难读懂,直接看代码运行结果分析好些,如果想看文字分析,可参考文末参考文章。
例子
#include <iostream>
using namespace std;
int main()
{
int a=5;
int *q=&a;
int **pp=&q;
//下面的两行输出在垂直方向上的相应值相同,由输出可知一级指针和二级指针的关系。
cout<<pp<<" "<<*pp<<" "<<*&pp<<" "<<**pp<<endl;
cout<<&q<<" "<< q <<" "<< &q <<" "<< *q <<endl;
return 0;
}
运行结果:

二级指针传参
#include <iostream>
using namespace std;
void make(int **pp)
{
**pp = 66;//这样只是改变了指向的值,即a, 指向没有改变
}
int main()
{
int a=5;
int *q=&a;
int **pp=&q;
cout<<"address:"<<&pp<<" "<<pp<<" "<<&q<<" "<<q<<" value:"<<*q<<" "<<a<<endl;
make(pp);
cout<<"address:"<<&pp<<" "<<pp<<" "<<&q<<" "<<q<<" value:"<<*q<<" "<<a<<endl;
return 0;
}
运行结果:

如果改为:
#include <iostream>
using namespace std;
void make(int **pp)
{
int * p=new int(66);
*pp=p; //这样便使用函数通过二级指针传参更改了一级指针的指向(值便也改了),但原指向的值不变。其实这和使用一级指针传参改变其指向的值类似,只不过多加了一级指针。
}
int main()
{
int a=5;
int *q=&a;
int **pp=&q;
cout<<"address:"<<&pp<<" "<<pp<<" "<<&q<<" "<<q<<" value:"<<*q<<" "<<a<<endl;
make(pp);
cout<<"address:"<<&pp<<" "<<pp<<" "<<&q<<" "<<q<<" value:"<<*q<<" "<<a<<endl;
}
运行结果:

指针引用传参
例子
#include<iostream>
using namespace std;
void make(int *pp)
{
pp=new int(66); //试图改变p指向的地址,但没有用,看运行结果。
}
int main()
{
int a=5;
int *p=&a; //指针变量指向一个int类型的地址
cout<<"address:"<<&a<<" value:"<<a<<endl;
cout<<"address:"<<p<<" value:"<<*p<<endl;
make(p);
cout<<"address:"<<p<<" value:"<<*p<<endl;
}
运行结果:

这里pp只是p的一个拷贝,pp在函数中相当于一个局部变量。
指针传递参数本质上是值传递的方式,它所传递的是一个地址值。
值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。
源自:C++中引用,指针,指针的引用,指针的指针
更改为:
#include<iostream>
using namespace std;
void make(int *&pp)
{
pp=new int(66); //此时pp相当于p的别名,所以改的就是指针p本身,所以更改成功。
}
int main()
{
int a=5;
int *p=&a; //指针变量指向一个int类型的地址
cout<<"address:"<<&a<<" value:"<<a<<endl;
cout<<"address:"<<p<<" value:"<<*p<<endl;
make(p);
cout<<"address:"<<p<<" value:"<<*p<<endl;
}
运行结果:

其实这里pp也是主调函数中p一个拷贝,但不同的是:任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量,所以最终是对于实参的操作。
再多说一点
引用传参与指针传参的不同还在于:指针传递参数时,指针中存放的也是实参的地址,但是在被调函数内部指针存放的内容可以被改变,即可能改变指向的实参,所以并不安全,而引用则不同,它引用的对象的地址一旦赋予,则不能改变。这也正是引用的初衷。
参考:
C++二级指针和指针引用传参的更多相关文章
- [ 随手记6 ] C/C++ 形参、实参、按值传参、指针传参、引用传参
个人原创: 1. 形参:形式上的参数,一般多在函数声明.函数定义的参数上: 2. 实参:实体参数,有实际的值,在运算上被循环使用的值: 3. 按值传参:按值,就是把实际的值传给函数内部: 4. 指针传 ...
- Go 到底有没有引用传参(对比 C++ )
Go 到底有没有引用传参(对比 C++ ) C++ 中三种参数传递方式 值传递: 最常见的一种传参方式,函数的形参是实参的拷贝,函数中改变形参不会影响到函数外部的形参.一般是函数内部修改参数而又不希望 ...
- Java中的new关键字和引用传参
先看看Java中如何使用new关键字创建一个对象的. [java] view plain copy public class Student { public String name; public ...
- Python中的引用传参
Python中函数参数是引用传递(注意不是值传递).对于不可变类型,因变量不能修改,所以运算不会影响到变量自身:而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量. 引用传参一: >& ...
- &符号 (弃用引用传参了,不要用!!)
写法一 $age = function grow($age) { $age += ; return $age; } echo grow($age) echo $age 写法二 $age = funct ...
- c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配
一 数组的结构:顺序存储,看谭浩强中的图,牢记 1.数组名指代一种数据结构:数组 现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的 ...
- C#调用C++ dll时,结构体引用传参的方法
写了一个C++的LogLog Logit 四参数等算法的接口dll,给C#调用,但是发现传参有问题 如 extern "C" _declspec(dllexport) bool ...
- c++拷贝构造函数引用传参
看一道C++面试题: 给出下述代码,分析编译运行的结果,并提供3个选项: A.编译错误 B.编译成功,运行时程序崩溃 C.编译运行正常,输出10 class A { private: int va ...
- C# 值传参和引用传参
值传递:对于个人理解,值传递就像是python中的深拷贝,值传递的内容和原来的内容是两份不同的东西,相互不影响. 引用传递:对于个人理解,引用传递就是python中的复杂多维list的浅拷贝,它传递的 ...
随机推荐
- HNOI2018/AHOI2018 游戏
这题放过了暴力其实就没啥意思了 虽然暴力复杂度很玄学,但是思维水平确实没啥 Description link 题意概述:现在有一条长度为 \(n\) 的链,有些边是有限制的 限制为能到某个点,才能经过 ...
- HTTP协议解析小白文
1. 什么是HTTP协议? HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本 ...
- 扯下Python的super()
注: Python 2.7.x 环境下 今晚搜东西无意中看到这篇Understanding Python super() with __init__() methods. 其实这篇老早就看过了, 不过 ...
- Spring boot 基于注解方式配置datasource
Spring boot 基于注解方式配置datasource 编辑 Xml配置 我们先来回顾下,使用xml配置数据源. 步骤: 先加载数据库相关配置文件; 配置数据源; 配置sqlSessionF ...
- Android开发学习1----AndroidStudio的安装、创建第一个Android Studio文件、Android Studio界面介绍和HelloWord!
移动开发的工具有很多:Android Studio,eclipse,Hbuilder等,其中,现如今最火的开发工具是Android Studio,Android Studio是谷歌自己推出的一款集成开 ...
- android 获得存储设备状态
1.获取存储器总大小,可用大小 File path= Environment.getExternalStorageDirectory();StatFs fs = new StatFs(path.get ...
- 七种常见经典排序算法总结(C++实现)
排序算法是非常常见也非常基础的算法,以至于大部分情况下它们都被集成到了语言的辅助库中.排序算法虽然已经可以很方便的使用,但是理解排序算法可以帮助我们找到解题的方向. 1. 冒泡排序 (Bubble S ...
- mysql,user表中各字段的含义
1.查询user表 select * from mysql.user 2.修改用户密码 ALTER user ' 3.user表中各字段的含义 Select_priv:用户可以通过SELECT命令选择 ...
- 监控 Linux 服务器活动的几个命令(watch top ac)
watch.top 和 ac 命令为我们监视 Linux 服务器上的活动提供了一些十分高效的途径. 为了在获取系统活动时更加轻松,Linux 系统提供了一系列相关的命令.在这篇文章中,我们就一起来看看 ...
- hdu 2586 How far away ?(LCA模板)(倍增法)
在dfs的过程中维护三个数组: deep[i],表示i点在树中的深度: grand[x][i],表示x的第2^i个祖先的节点编号: dis[x][i],表示x到它2^i祖 #include<io ...