声明对对象和赋值运算符的引用

Posted

技术标签:

【中文标题】声明对对象和赋值运算符的引用【英文标题】:Declaring a reference to object and the assignment operator 【发布时间】:2011-10-16 17:40:33 【问题描述】:

我觉得这个问题足够基本,可以在某个地方找到,但我似乎无法找到答案。

假设我有这个代码:

//class member function
std::map< std::string, std::string > myMap;

const std::map< std::string, std::string >& bar()

   return myMap;


void myFunc( std::map< std::string, std::string >& foo1 )

   foo1 = bar();
   std::map< std::string, std::string >& foo2 = bar();

我的理解是,如果我开始使用 foo2,因为 foo2 是对与 bar() 返回的相同实例的引用,所以我对 foo2 所做的任何事情都会反映在 myMap 中。但是 foo1 呢? foo1 是否获得了 myMap 的副本,或者它是否也指向与 bar() 返回的实例相同的实例? c++ 标准库说 std::map 的赋值运算符会将元素复制过来,但这是否意味着在 foo2 的声明中并未真正调用赋值运算符?

谢谢!

【问题讨论】:

【参考方案1】:

引用在 C++ 中不可重新安装。这意味着一旦它们被初始化,就不能重新分配它们。相反,任何分配实际上都涉及被引用的对象。所以在你的代码中,

foo1 = bar();
std::map< std::string, std::string >& foo2 = bar();

第一行在作为参数传递给myFunc 的对象上调用std::map::operator=。在那之后,foo1 Stills 指的是同一个对象——但它的值(例如它所包含的元素)很可能已经改变了。

注意第二行是不是的赋值,如果你有任何疑问的话。相反,它是一个初始化。由于bar的返回类型实际上是std::map&lt;std::string, std::string&gt; const&amp;,所以不能绑定到std::map&lt;std::string, std::string&gt;&amp;所以是编译错误。


为了扩展事物的“哲学”方面,C++ 引用被设计为尽可能透明,并不真正作为对象存在。这是使用该术语的 C++ 标准含义(它与 OOP 无关):这意味着例如引用类型 not 有大小。相反,sizeof(T&amp;) == sizeof(T)。同样,引用没有地址,也不可能形成指针或对引用的引用:给定int&amp; ref = i;,然后是&amp;ref == &amp;i

因此,引用是有意使用的,就像被引用的对象被自己使用一样。在引用的生命周期中发生的唯一特定于引用的事情是它的初始化:它可以绑定到什么以及它在生命周期中的含义。

【讨论】:

+1 谢谢,我自己学到了一些新东西。我刚刚做了一个测试,我确实 100% 错了,你是对的 =-) 好的,太好了!谢谢,我真正需要知道的是赋值运算符是在 foo1 中调用的,而不是在 foo2 中调用的。很好的解释,谢谢! @Luc 如果可能的话,你能复习一下为什么一般不使用引用变量吗?我对它们是什么有了更好的理解(感谢您的回答),但似乎编码人员通常更喜欢指针。是冗余吗?范围有限? @MannyD 我的经历和你的不一样。我经常使用引用并看到引用用作局部变量,对于这种用法,它们通常比指针更可取。 @Luc 我想我应该澄清一下。我一直在函数参数列表中看到/使用它们,但我不明白你为什么要在代码体中声明一个,甚至作为类成员。【参考方案2】:

线

foo1 = bar();

创建一个副本(因为这是map 的赋值运算符所做的)。

【讨论】:

返回对全局变量的引用似乎很奇怪,不是吗? @0A0D:不是真的,它可以用于封装,如果“全局”变量实际上没有外部链接。或者您可以返回对全局变量 a 或全局变量 b 的引用。

以上是关于声明对对象和赋值运算符的引用的主要内容,如果未能解决你的问题,请参考以下文章

在Java中,如何返回对对象的引用,以便可以使用赋值运算符修改对象

为啥移动赋值运算符应该返回对 *this 的引用 [重复]

c++中为啥赋值运算符重载返回类型是引用

剑指offer:赋值运算符函数

赋值运算符重载函数 引用返回 与 对象返回

赋值函数(运算符重载)