声明对对象的引用和赋值运算符
我觉得这个问题足够基本,可以在某个地方存在,但我似乎无法找到答案。
假设我有这样的代码:
//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 的声明中并未真正调用赋值运算符?
谢谢!
I feel like this question is basic enough to be out there somewhere, but I can't seem to be able to find an answer for it.
Suppose I have this code:
//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();
}
My understanding is that if I start using foo2, since foo2 is a reference to the same instance as what bar() returns, anything I do with foo2 will be reflected in myMap. But what about foo1? Does foo1 get a copy of myMap or does it also point to the same instance as what bar() returns? The c++ standard library says that the assignment operator for std::map will copy the elements over, but then does that mean the assignment operator is not really invoked in the declaration of foo2?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 C++ 中,引用不可重新插入。这意味着一旦它们被初始化,您就无法重新分配它们。相反,任何分配实际上都涉及引用的对象。因此,在您的代码中,
第一行对作为参数传递给
myFunc
的对象调用std::map::operator=
。之后,foo1
stills 引用同一个对象——但它的值(例如它保存的元素)很可能已经改变。请注意,如果您对第二行有任何疑问,则第二行不是赋值。相反,它是一个初始化。由于 bar 的返回类型实际上是
std::map; const&
,它无法绑定到std::map&
所以这是一个编译错误。为了扩展事物的“哲学”方面,C++ 引用被设计为尽可能透明,并且并不真正作为对象存在。这是使用该术语的 C++ 标准含义(与 OOP 无关):这意味着引用类型没有有大小。相反,
sizeof(T&) == sizeof(T)
。类似地,引用没有地址,并且不可能形成指针或对引用的引用:给定int& ref = i;
,然后&ref == &i
。因此,引用是有目的地使用的,就像所引用的对象本身正在被使用一样。在引用的生命周期中发生的唯一特定于引用的事情是它的初始化:它可以绑定到什么以及它在生命周期方面意味着什么。
References are not reseatable in C++. This means that once they're initialized, you can't reassign them. Instead, any assignment actually involve the referred object. So in your code,
the first line calls
std::map::operator=
on the object that was passed as a parameter tomyFunc
. After that,foo1
stills refers to that same object -- but its value (e.g. what elements it holds) may very well has been changed.Note that the second line is not assignment if there ever was any doubt that it was in your mind. Instead, it is an initialization. Since the return type of bar is actually
std::map<std::string, std::string> const&
, it can't bind tostd::map<std::string, std::string>&
so it's a compile error.To expand on the 'philosophical' side of things, C++ references are designed to be as transparent as possible and don't really exist as objects. This is using the C++ Standard meaning of the term (it is not related to OOP): it means that for instance reference types do not have a size. Instead,
sizeof(T&) == sizeof(T)
. Similarly, references do not have addresses and it's not possible to form a pointer or a reference to a reference: givenint& ref = i;
, then&ref == &i
.References are thus purposefully meant to be used as if the referred objects were being used themselves. The only thing reference-specific that happens in the lifetime of a reference is its initialization: what it can bind to and what it means in terms of lifetime.
该行
创建一个副本(因为这就是
map
的赋值运算符所做的)。The line
creates a copy (because that's what
map
's assignment operator does).