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

时间:2011-07-31 00:21:09

标签: c++ reference assignment-operator

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

假设我有这段代码:

//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的声明中并没有真正调用赋值运算符?

谢谢!

2 个答案:

答案 0 :(得分:16)

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

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

第一行调用std::map::operator=作为参数传递给myFunc的对象。在此之后,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

因此,有意使用引用,就像引用的对象本身一样。在引用的生命周期中发生的唯一特定于引用的是它的初始化:它可以绑定到什么以及它在生命周期中意味着什么。

答案 1 :(得分:0)

该行

foo1 = bar();

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