
目录
作为一名 ikun,我最喜欢的明星就是坤坤,但是坤坤又不只叫坤坤,因为他的成名之作《鸡你太美》,ikun们就经常亲切的叫他鸡哥。
这个过程中,鸡哥就是我们 ikun 给偶像坤坤起的外号。而C++中也有这一功能可以给自己喜欢的变量起外号。下面让我们和坤坤一起,学习C++的引用!

引用同样是 C++ 相对于C语言的又一个扩充。引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据。引用不是新定义一个变量,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
直接看概念可能有点抽象,我们想一下偶像坤坤被起外号的过程,就能理解了。坤坤又被粉丝们戏称为鸡哥,这里鸡哥就是偶像坤坤的别名,代表的都是坤坤这个人。世界不会因为粉丝们给坤坤起了个别名叫鸡哥,就凭空创造出一个人叫鸡哥。
声明方法如下:
类型 & 引用变量名(对象名) = 引用实体;
注意:这里的&符号并不是C语言中的取地址的意思,在C++中&又有引用的意思。
注意:引用类型必须和引用实体是同种类型的。
下面举个例子:
void ikun()
{
string kunkun = "我是坤坤";
string& jige = kunkun; //给kunkun取个外号叫jige
printf("kunkun的地址:%p\n", &kunkun);
cout << "kunkun的打印:" << kunkun << endl;
printf("jige的地址:%p\n", &jige);
cout << "jige的打印:" << jige << endl;
}
int main()
{
ikun();
return 0;
}

下面本ikun以身试法,写一段没有初始化的引用:
void ikun()
{
string kunkun = "我是坤坤";
string& jige;
cout << "kunkun的打印:" << kunkun << endl;
cout << "jige的打印:" << jige << endl;
}

这个理解起来很简单。就像我的偶像坤坤。他在经典歌曲《鸡你太美》中被ikun们称为鸡哥,但是后来,有一拨人喜欢上了他在这个节目中的篮球表演,于是,有人又以蓝球哥称呼他。还有一批人,喜欢上了他的中分发型,于是另外一批人,以中分哥称呼他。
这里的鸡哥、中分哥、篮球哥都是坤坤的外号或者说是坤坤的别名。
C++里面的引用也是一样,你可以给你喜欢的变量取很多的别名。
下面我举个例子:
void ikun()
{
string kunkun = "我是坤坤";
string& jige = kunkun;
string& zhongfen = kunkun;
string& lanqiu = kunkun;
printf("kunkun的地址 :%p\n", &kunkun);
printf("jige的地址 :%p\n", &jige);
printf("zhongfen的地址:%p\n", &zhongfen);
printf("lanqiu的地址 :%p\n", &lanqiu);
}
int main()
{
ikun();
return 0;
}

这句话的意思是,我们给一个变量去了外号后,以后这个外号只属于这个变量了,其他变量不能使用这个外号。
就像在我们ikun的眼中,鸡哥就是坤坤的外号,其他人不允许使用鸡哥这个外号!
我们下面看这段代码,有个叫做丽丽的变量,也想和坤坤一样取个外号叫做鸡哥。
这当然不会被我们ikun允许,运行一下,看编译器如何暴打丽丽!
void ikun()
{
string kunkun = "我是坤坤";
string lili = "我是丽丽";
string& jige = kunkun;
string& jige = lili;
cout << jige << endl;
}
int main()
{
ikun();
return 0;
}

如果在声明引用时用const修饰,被声明的引用就是常引用。
非const的引用只能绑定到普通的对象,而不能绑定到常对象;常引用可以绑定到常对象。一个常引用绑定的无论是普通的对象还是常对象,通过该引用访问的对象只能当做常对象对待,该对象拥有常对象的性质。
错误方式:
void ikun()
{
const int is_ikun = 1;
int& good = is_ikun;
}
正确方式:
void ikun()
{
const int is_ikun = 1;
const int& good = is_ikun;
}

在定义或声明函数时,我们可以将函数的形参指定为引用的形式,这样在调用函数时就会将实参和形参绑定在一起,让它们都指代同一份数据。如此一来,如果在函数体中修改了形参的数据,那么实参的数据也会被修改,从而拥有“在函数内部影响函数外部数据”的效果。
其实很好理解,我们给坤坤起的外号叫鸡哥,现在我说,让鸡哥去打篮球。去的人自然就是坤坤,看似是让鸡哥去做,其实结果就是坤坤,对鸡哥的改变就是对坤坤的改变。

像下面这一,利用引用也可以完成“在函数内部影响函数外部数据”的效果。
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
如下,一个做返回值的小例子:
int &ADD (int r)
{
r += 10;
return r;
}
值得注意的是,引用做返回值看似很简单,但是里面有个小坑!!
那就是在将引用作为函数返回值时应该注意一个小问题,就是不能返回局部数据(例如局部变量、局部对象、局部数组等)的引用,因为当函数调用完成后局部数据就会被销毁,有可能在下次使用时数据就不存在了。所以,如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回。
此时,一位悲催的程序员再次以身试法,帮助ikun避坑:
int& Add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int& ret = Add(1, 2);
Add(3, 4);
cout << "Add(1, 2) is :" << ret << endl;
return 0;
}


在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
但是在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。
分析下面的代码:
//引用
int main()
{
int a = 10;
int& ra = a;
cout<<"&a = "<<&a<<endl;
cout<<"&ra = "<<&ra<<endl;
return 0;
}
//指针
int main()
{
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
return 0;
}
我们来看下引用和指针的汇编代码对比:

引用和指针的不同点:


📢📢📢📢📢📢
💗 你正在阅读 【子夜的星】 的 C++笔记
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中帮我指正吧
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
我正在尝试将一个资源属性的默认值设置为另一个属性的值。我正在为我正在构建的tomcat说明书定义一个资源,其中包含以下定义。我想要可以独立设置的“名称”和“服务名称”属性。当未设置服务名称时,我希望它默认为为“名称”提供的任何内容。以下不符合我的预期:attribute:name,:kind_of=>String,:required=>true,:name_attribute=>trueattribute:service_name,:kind_of=>String,:default=>:name注意第二行末尾的“:default=>:name”。当我在Recipe的新block中引用我
如thisanswer中所述,Array.new(size,object)创建一个数组,其中size引用相同的object。hash=Hash.newa=Array.new(2,hash)a[0]['cat']='feline'a#=>[{"cat"=>"feline"},{"cat"=>"feline"}]a[1]['cat']='Felix'a#=>[{"cat"=>"Felix"},{"cat"=>"Felix"}]为什么Ruby会这样做,而不是对object进行dup或clone? 最佳答案 因为那是thedocumenta
假设我有一个可枚举对象enum,现在我想获取第三个项目。我知道一种通用方法是转换成数组,然后使用索引访问,如:enum.to_a[2]但这种方式会创建一个临时数组,效率可能很低。现在我使用:enum.each_with_index{|v,i|breakvifi==2}但这非常丑陋和多余。执行此操作最有效的方法是什么? 最佳答案 你可以使用take剥离前三个元素,然后剥离last从take给你的数组中获取第三个元素:third=enum.take(3).last如果您根本不想生成任何数组,那么也许:#Ifenumisn'tanEnum
代码:threads=[]Thread.abort_on_exception=truebegin#throwexceptionsinthreadssowecanseethemthreadseputs"EXCEPTION:#{e.inspect}"puts"MESSAGE:#{e.message}"end崩溃:.rvm/gems/ruby-2.1.3@req/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:478:inload_missing_constant':自动加载常量MyClass时检测到循环依赖稍加研究后,
我正在跟踪我们的应用程序(ruby2.1)中的内存泄漏问题。我正在使用这两种技术:ObjectSpace.dump_all将所有对象转储到JSON流,然后进行离线分析。我使用的第二种技术是使用ObjectSpace.reachable_objects_from进行实时分析。在这两种方式中,我发现我泄漏的对象被一个对象RubyVM::Env引用。任何人都可以向我解释什么是RubyVM::Env。如何删除这些引用? 最佳答案 RubyVM::Env是一个包含变量引用的内部ruby类。这是我的测试:require'objspace'a
这个问题不是很有用因为themethodreferenceoperatorwasremovedfromRuby2.7.0发布前。由于历史原因,这个问题被搁置了。Ruby2.7.0-preview1引入了方法引用运算符.:作为实验性功能。(更多here和here)。有一些抽象示例可用于说明如何使用这个新运算符:method=42.:to_s=>#method.receiver=>42method.name=>:to_smethod.call=>"42"和:method=File.:read=>#method.call('/Users/foo/.zshrc')=>"exportZSH=$H
在我的应用程序中我有classUserincludeUser::FooendUser::Foo定义在app/models/user/foo.rb现在我正在使用一个定义了自己的Foo类的库。我收到此错误:warning:toplevelconstantFooreferencedbyUser::FooUser仅引用具有完整路径的Foo,User::Foo,而Foo实际上从来没有指的是Foo。这是怎么回事?更新:才想起我之前遇到过同样的问题,在问题1中看到这里:HowdoIrefertoasubmodule's"fullpath"inruby? 最佳答案
我想通过JSON获取Wikiquote页面的结构化版本(基本上我需要所有短语)示例:http://en.wikiquote.org/wiki/Fight_Club_(film)我试过:http://en.wikiquote.org/w/api.php?format=xml&action=parse&page=Fight_Club_(film)&prop=text但我得到了所有HTML源代码。我需要每个pharse作为数组的一个元素我如何使用DBPEDIA实现这一目标? 最佳答案 首先,我不确定您是否可以使用DBpedia查询wiki
有没有办法让我的en.yml文件包含一个常量?#en.ymlfoo:bar:IloveBAZsomuch!#initializers/constants.rbBAZ="stackoverflow.com"I18n.t("foo.bar")->"Ilovestackoverflow.comsomuch!"?如果没有,有没有办法自己引用yaml文件?foo:bar:Ilove*baz*somuch!baz:stackoverflow.comI18n.t("foo.bar")->"Ilovestackoverflow.comsomuch!" 最佳答案