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的浅拷贝,它传递的 ...
随机推荐
- tensorflow模型
图像模型 YOLOv3 , 地址 https://pjreddie.com/darknet/yolo/ vgg , 参考 https://github.com/tensorflow/models/bl ...
- vue 常用知识点
1.数据变更,页面渲染完成 this.$nextTick(function(){ alert('v-for渲染已经完成') }) 2.iview select组件 setQuery用法 <Sel ...
- 封装FTP类
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.IO; using ...
- StartDT AI Lab | 数据增强技术如何实现场景落地与业务增值?
有人说,「深度学习“等于”深度卷积神经网络算法模型+大规模数据+云端分布式算力」.也有人说,「能够在业内叱咤风云的AI都曾“身经百战”,经历过无数次的训练与试错」.以上都需要海量数据做依托,对于那些数 ...
- mysql字段修改脚本
-- help_text:帮助说明 -- help_content -- raw USE pro_seal_chip_sell_portal_v1; -- 表修改ALTER TABLE `help_t ...
- Nuxt.js学习(二) --- Nuxt目录结构详解、Nuxt常用配置项、Nuxt路由配置和参数传递
[TOC] 1.Nuxt目录结构详解 Nuxt项目文件目录结构 |-- .nuxt // Nuxt自动生成,临时的用于编辑的文件,build |-- assets // 用于组织未编译的静态资源入LE ...
- lower()|upper()|Traceback|title()|字符串合并|rstrip|lstrip|str()|
print ("hello,world!") sentence = "yyyy" print (sentence.lower()) print (sentenc ...
- 爬虫笔记(三)——HTTP协议请求实战
如果要进行客户端与服务器端之间的消息传递,我们可以使用HTTP协议请求进行. HTTP协议请求主要分为6种类型,各类型的主要作用如下: GET请求:GET请求会通过URL网址传递信息,可以直接在URL ...
- crontab不执行service命令
我这里的需求是每30分钟重启一次 写成下面的格式就可以正确执行了,后面执行的命令写绝对路径 */30 * * * * /usr/bin/supervisorctl restart all
- 【shell】概述
功能简介 批量自动初始化系统(update,软件安装,时区设置,安全策略...) 批量自动部署软件(LAMP,LNMP,Nginx,LVS,Tomcat) 管理应用程序(KVM,集群管理扩容,MySQ ...