深入理解C++引用传递与指针传递的区别

C++中的引用传递是通过引用将参数传递给函数,使函数能够直接访问传递的参数。但是,引用传递并不改变被引用对象的内存指向,而是允许函数在不复制参数的情况下对其进行操作。这意味着,虽然函数可以修改被引用对象的值,但不能修改被引用对象的地址或指向其他对象的指针。

实例:


#include <iostream> #include <string.h> using namespace std; class Cat { public: // 公共成员函数 Cat(string alias){ this->alias= alias; } string getAlias(){ return this->alias; } void setAlias(string alias){ this->alias = alias; } private: // 私有成员变量 string alias; }; void changeCat(Cat *& c){ cout<<"\n----------changeCat is start---------------\n"<<endl; cout<<c->getAlias()<<endl; cout<<"c引用变量的值:"<<c<<endl; cout<<"c引用变量的内存地址:"<<&c<<endl; c= new Cat("huahua"); cout<<"****changeCat函数内部改变了引用变量c的指向之后****"<<endl; cout<<c->getAlias()<<endl; cout<<"c引用变量的值:"<<c<<endl; cout<<"c引用变量的内存地址:"<<&c<<endl; cout<<"\n----------changeCat is over---------------\n"<<endl; } int main(){ Cat* cat1 =new Cat("mimi"); Cat * &pt = cat1; cout<<"pt引用变量的值:"<<pt<<endl; cout<<"pt引用变量的内存地址:"<<&pt<<endl; changeCat(pt); printf("-------in main() 调用changeCat之后--------\n"); cout<<pt->getAlias()<<endl; cout<<"pt引用变量的值:"<<pt<<endl; cout<<"pt引用变量的内存地址:"<<&pt<<endl; return 0; }

运行结果:


pt引用变量的值:0x1eae040 pt引用变量的内存地址:0x7ffd17bb6818 ----------changeCat is start--------------- mimi c引用变量的值:0x1eae040 c引用变量的内存地址:0x7ffd17bb6818 ****changeCat函数内部改变了引用变量c的指向之后**** huahua c引用变量的值:0x1eae090 c引用变量的内存地址:0x7ffd17bb6818 ----------changeCat is over--------------- -------in main() 调用changeCat之后-------- huahua pt引用变量的值:0x1eae090 pt引用变量的内存地址:0x7ffd17bb6818

我们发现引用传递其引用c所指向的内存单元,从始至终都没有发生改变。由于这个内存单元是指针类型,我们可以修改内存单元里的值,但是不能修改内存单元本身的地址,即让引用c指向一个新的内存单元。

所以引用传递的本质是:引用传递能够将变量或对象本身作为参数传递,而不是复制一份副本后传递给形参。

引用传递的主要作用有两点:

  1. 函数内部可修改变量或对象。函数返回后,函数调用者得到的也是被修改后的值。常见场景:① 函数需要返回多个值,由于return只能返回一个值,因此可以将其他值以引用传递的形式修改。② 控制递归过程,可以令参数为引用传递,每次递归执行函数体,就会修改参数,当参数等于某个值时递归结束。
  2. 也是最重要的作用,引用传递可以避免对象传递时的复制构造。如果函数参数是对象,且采用值传递,则从调用者传到被调函数的参数,需要调用一次复制构造函数。如果这个对象很大,复制构造的开销就会很高。反观引用传递,它传递对象本身,可以完美规避复制构造的过程,极大减少时空开销。最后,如果不希望函数体更改引用传递的对象,则应在对象参数前加const限定,即const引用传递。

2.指针传递

C++中的指针传递,其本质是传递给形参的指针仍是实参的一个拷贝。这一点就和引用传递有了本质上的区别了。指针传递可以理解成实参和形参两个指针是指向同一地址的指针,你可以通过这两个指针修改这个地址上所指向的内存单元的内容,却不能通过形参去修改实参的指向。

实例:


#include <iostream> #include <string.h> using namespace std; class Cat { public: // 公共成员函数 Cat(string alias){ this->alias= alias; } string getAlias(){ return this->alias; } void setAlias(string alias){ this->alias = alias; } private: // 私有成员变量 string alias; }; void changeCat(Cat *c){ cout<<"\n----------changeCat is start---------------\n"<<endl; cout<<c->getAlias()<<endl; cout<<"c指针变量的值:"<<c<<endl; cout<<"c指针变量的内存地址:"<<&c<<endl; c= new Cat("huahua"); //c->setAlias("huahua"); cout<<"****changeCat函数内部改变了指针变量c的指向之后****"<<endl; cout<<c->getAlias()<<endl; cout<<"c指针变量的值:"<<c<<endl; cout<<"c指针变量的内存地址:"<<&c<<endl; cout<<"\n----------changeCat is over---------------\n"<<endl; } /* Cat * changeCat(Cat *c){ cout<<c->getAlias()<<endl; cout<<&c<<endl; c= new Cat("huahua"); cout<<c->getAlias()<<endl; cout<<&c<<endl; return c; }*/ int main(){ Cat *pt = new Cat("mimi"); //c1 = changeCat(c1); cout<<"pt指针变量的值:"<<pt<<endl; cout<<"pt指针变量的内存地址:"<<&pt<<endl; changeCat(pt); printf("-------in main() 调用changeCat之后--------\n"); cout<<pt->getAlias()<<endl; cout<<"pt指针变量的值:"<<pt<<endl; cout<<"pt指针变量的内存地址:"<<&pt<<endl; return 0; }

运行结果:


pt指针变量的值:0x1b76040 pt指针变量的内存地址:0x7fffeb039110 ----------changeCat is start--------------- mimi c指针变量的值:0x1b76040 c指针变量的内存地址:0x7fffeb0390c8 ****changeCat函数内部改变了指针变量c的指向之后**** huahua c指针变量的值:0x1b76090 c指针变量的内存地址:0x7fffeb0390c8 ----------changeCat is over--------------- -------in main() 调用changeCat之后-------- mimi pt指针变量的值:0x1b76040 pt指针变量的内存地址:0x7fffeb039110

小结:

引用传递的本质是:引用传递能够将变量或对象本身作为参数传递,而不是复制一份副本后传递给形参。而指针传递,其本质是实参传递给形参的指针仍是实参的一个拷贝(副本)。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值