我不得不简化一些代码来提出这个问题。但是,在下面的代码中,我没有声明x
作为引用类型这一事实意味着一旦函数退出,我的减量更改将被“遗忘”吗?
解决此问题的最明智的方法是将x
声明为AnotherClass& x
?
void MyClass::myFunc(unordered_map<int, AnotherClass>* dictionary, int z, int y){
AnotherClass x = dictionary->at(z);
//Does this change on x get "forgotten" in terms of what dictionary stores
//once myFunc() has finished, because x is not a reference/pointer type?
x.changeSomething(y--);
}
class MyClass{
public:
private:
myFunc(unordered_map<int, AnotherClass>* dictionary, int z);
unordered_map<int, AnotherClass>* dictionary
};
答案 0 :(得分:3)
正确。 x
是dictionary
元素的副本。您正在对副本应用更改,该副本是函数的本地副本。你应该在呼叫方看不到任何效果。您可以参考,也可以直接对at
:
dictionary->at(z).changeSomething(z--);
请注意,这与函数内部的代码无关。
答案 1 :(得分:2)
在编写Thing t = s;
时,在Java或C#等语言中,实际上创建的别名t
引用内存中与s
引用的对象相同的对象。但是,在C ++中,值和别名是严格分开的:
Thing t = s;
是关于制作s
Thing& t = s;
是关于创建引用同一对象的别名而不是s
(引用)Thing* t = &s;
是关于创建引用同一对象的别名而不是s
(指针)引用和指针之间的区别并不重要,重要的是副本和别名之间的区别。
根据你的例子:
// Fix 1: take dictionary by *reference* and not by *pointer*.
void MyClass::myFunc(std::unordered_map<int, AnotherClass>& dictionary, int z, int y){
// Fix 2: dictionary.at(z) returns a "AnotherClass&"
// that is an alias to the element held within the dictionary.
// Make sure not to accidentally make a copy by using that "&"
// for the type of x.
AnotherClass& x = dictionary.at(z);
// "x" is now a mere alias, the following call is thus applied
// to the value associated to "z" within "dictionary".
x.changeSomething(y--);
}
请注意,在这种情况下你可以写dictionary.at(z).changeSomething(y--);
;但是有几个缺点:
x
多次,则将其命名为更清晰。