2011-07-31 36 views
10

我觉得这个问题已经足够基本,可以在某处找到,但我似乎无法找到答案。声明对象和赋值运算符的引用

假设我有这样的代码:

//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的是同一个实例的引用作为什么吧()返回时,任何事情我foo2的办会体现在myMap中。但是foo1呢? foo1是否获取myMap的副本,或者它是否指向与bar()返回的实例相同的实例? C++标准库说std :: map的赋值操作符会将元素复制过来,但这是否意味着赋值操作符在foo2的声明中没有被真正调用?

谢谢!

回答

15

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

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

第一行调用被作为参数传递myFunc的对象std::map::operator=。之后,foo1剧照指的是同一个对象 - 但它的价值(例如它拥有的元素)可能已经改变。

请注意,第二行是而不是如果您有任何疑问,请将其分配给您。相反,它是一个初始化。由于返回类型实际上是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

参考文献因此有意使用好像所提及的对象本身正在使用。在引用的生命周期中唯一引用特定的是它的初始化:它可以绑定到什么以及它在生命周期方面意味着什么。

+0

+1谢谢,我自己学到了一些新东西。我只是做了一个测试,我确实是100%错误,你是对的= - ) – flumpb

+0

好了!谢谢,我真正需要知道的是赋值运算符在foo1中调用,并且不在foo2中调用。很好的解释,谢谢! – bhh1988

+0

@Luc如果可能,你能否理解为什么通常不使用引用变量?我对它们是什么有了更好的理解(感谢你的回答),但似乎编程人员普遍赞成对它的指示。它是多余的吗?范围有限? –

0

线

foo1 = bar(); 

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

+0

似乎很奇怪返回一个全局变量的引用,不是吗? – 2011-07-31 00:33:37

+0

@ 0A0D:如果“全局”变量实际上没有外部链接,则不是真的,它可以用于封装。或者你可能返回一个对全局变量'a'或全局变量'b'的引用。 –