前提

一级指针和引用

已经清晰一级指针和引用。

可参考:指针和引用与及指针常量和常量指针 或查阅其他资料。

一级指针和二级指针

个人觉得文字描述比较难读懂,直接看代码运行结果分析好些,如果想看文字分析,可参考文末参考文章。

例子

#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++二级指针和指针引用传参的更多相关文章

  1. [ 随手记6 ] C/C++ 形参、实参、按值传参、指针传参、引用传参

    个人原创: 1. 形参:形式上的参数,一般多在函数声明.函数定义的参数上: 2. 实参:实体参数,有实际的值,在运算上被循环使用的值: 3. 按值传参:按值,就是把实际的值传给函数内部: 4. 指针传 ...

  2. Go 到底有没有引用传参(对比 C++ )

    Go 到底有没有引用传参(对比 C++ ) C++ 中三种参数传递方式 值传递: 最常见的一种传参方式,函数的形参是实参的拷贝,函数中改变形参不会影响到函数外部的形参.一般是函数内部修改参数而又不希望 ...

  3. Java中的new关键字和引用传参

    先看看Java中如何使用new关键字创建一个对象的. [java] view plain copy public class Student { public String name; public  ...

  4. Python中的引用传参

    Python中函数参数是引用传递(注意不是值传递).对于不可变类型,因变量不能修改,所以运算不会影响到变量自身:而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量. 引用传参一: >& ...

  5. &符号 (弃用引用传参了,不要用!!)

    写法一 $age = function grow($age) { $age += ; return $age; } echo grow($age) echo $age 写法二 $age = funct ...

  6. c指针与数组,传参问题,指针数组与数组指针的区别,二维数组动态内存分配

    一 数组的结构:顺序存储,看谭浩强中的图,牢记 1.数组名指代一种数据结构:数组 现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的 ...

  7. C#调用C++ dll时,结构体引用传参的方法

    写了一个C++的LogLog Logit 四参数等算法的接口dll,给C#调用,但是发现传参有问题 如 extern "C" _declspec(dllexport)  bool ...

  8. c++拷贝构造函数引用传参

    看一道C++面试题: 给出下述代码,分析编译运行的结果,并提供3个选项: A.编译错误  B.编译成功,运行时程序崩溃  C.编译运行正常,输出10 class A { private: int va ...

  9. C# 值传参和引用传参

    值传递:对于个人理解,值传递就像是python中的深拷贝,值传递的内容和原来的内容是两份不同的东西,相互不影响. 引用传递:对于个人理解,引用传递就是python中的复杂多维list的浅拷贝,它传递的 ...

随机推荐

  1. c语言中用简单方法对多维数组进行初始化

    例:int array[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12}; 说明:a.由4*3可知,本二维数组包含12个元素,因此初始化时array[0][0] = 1 ,ar ...

  2. 你需要知道的 N 种抓取 dump 的工具

    原总结注册表debug调试dump转储文件windbgprocdump 前言 今天,向大家介绍几种可以抓取应用程序转储文件的工具及基本使用方法.更详细的用法,请参考每个工具对应的帮助文档.如果你还不清 ...

  3. 第7节 Arrays工具类

    package cn.itcast.day08.demo04; import java.util.Arrays; /*java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法, ...

  4. 有几个水洼(DFS)

    #include <iostream> #include<cstdio> using namespace std; #define maxn 105 char field[ma ...

  5. 显著水平|区间估计|假设检验|显著性|第一类错误|Ⅱ类错误|β错误|t检验|连续性矫正|二项分布的假设检验|样本百分率|

    第三章 假设检验 区间估计与假设检验的基本区别? 上一章中讨论了置信区间的估计方法.它是利用样本数据,以抽样总体的分布为理论基础,用一定的概率保证来计算出原总体中未知参数的区间范围.特别值得注意的是: ...

  6. tensroflow中如何计算特征图的输出及padding大小

    根据tensorflow中的conv2d函数,我们先定义几个基本符号 1.输入矩阵 W×W,这里只考虑输入宽高相等的情况,如果不相等,推导方法一样,不多解释. 2.filter矩阵 F×F,卷积核 3 ...

  7. sftp安装(linux)

    --整理于网络 1. 查看openssh版本ssh -Vopenssh版本必须大于4.8p12. 创建sftp组groupadd sftp3. 创建sftp用户useradd -g sftp -s / ...

  8. 吴裕雄--天生自然 pythonTensorFlow自然语言处理:交叉熵损失函数

    import tensorflow as tf # 1. sparse_softmax_cross_entropy_with_logits样例. # 假设词汇表的大小为3, 语料包含两个单词" ...

  9. 第一章:ESXi6.7虚拟化环境安装

    1.1 硬件环境及镜像引导准备 1.1.1       硬件和系统资源 要安装ESXi6.7,硬件和系统资源必须满足下列要求: ESXi 6.7 要求主机至少具有两个 CPU 内核,生产环境中需要根据 ...

  10. Java之异常的处理(try-catch)

    import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java. ...