声明对对象的引用和赋值操作符

Declaring a reference to object and the assignment operator

本文关键字:赋值操作符 引用 对象 声明      更新时间:2023-10-16

我觉得这个问题很基本,应该在某个地方出现,但我似乎找不到答案。

假设我有这样的代码:
//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的声明中没有真正调用赋值操作符?

谢谢!

c++中不允许引用。这意味着一旦它们被初始化,就不能重新赋值。相反,任何赋值实际上都涉及被引用的对象。在你的代码中,

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

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

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


为了从哲学的角度展开,c++引用被设计得尽可能透明,而不是作为对象存在。这使用了c++标准中术语的含义(它与OOP无关):它意味着实例引用类型没有有大小。取而代之的是sizeof(T&) == sizeof(T)。同样,引用也没有地址,也不可能形成指向引用的指针或引用:给定int& ref = i;,则&ref == &i

因此,

引用被有意地使用,就好像被引用的对象本身正在被使用一样。在引用的生命周期中发生的唯一与引用相关的事情是它的初始化:它可以绑定到什么,以及它在生命周期中意味着什么。

foo1 = bar();

创建一个副本(因为map的赋值操作符就是这样做的)。