我觉得这个问题很基本,可以在某个地方出现,但我似乎无法找到答案。
假设我有这段代码:
//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的声明中并没有真正调用赋值运算符?
谢谢!
答案 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
的赋值运算符所做的)。