在Java中,如果您有以下代码,则list1和list2最终指向同一个对象,因此list2中的更改将导致list1发生更改。
ArrayList<Integer> list1 = new ArrayList<Integer>();
list1.add(1);
list1.add(2);
list1.add(3);
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2 = list1;
list2.set(0, 10);
for(int i =0; i<list1.size(); i++){
System.out.println(list1.get(i));
}
for(int i =0; i<list2.size(); i++){
System.out.println(list2.get(i));
}
输出最终是:
10
2
3
10
2
3
但是,在C ++中,行为是不同的?
vector<int> list1;
list1.push_back(1);
list1.push_back(2);
list1.push_back(3);
vector<int> list2;
list2 = list1;
list2.at(0) = 10;
for(int i =0; i<list1.size(); i++){
cout << list1[i] << endl;
}
for(int i=0; i<list2.size(); i++){
cout << list2[i] << endl;
}
输出最终为:
1
2
3
10
2
3
有人可以解释一下吗?
答案 0 :(得分:3)
详细说明我的评论:
在Java中,=
运算符on(赋值兼容)引用类型只是复制引用值。 (如果您来自C / C ++世界,请考虑指针。)要记住的关键是在Java中,任何变量都不是对象;它是对象的原始值或引用。
在您的C ++示例中,=
运算符正在处理实际对象,而不是引用。 (对于其他数据类型,故事可能会有所不同。)来自the docs for std::vector::operator=
:
将新内容分配给容器,替换其当前内容,并相应地修改其大小。
所以在C ++中,list2
在赋值后仍然是一个单独的vector
对象,只有list1
的内容副本。在Java中,一旦您将ArrayList
重新分配为与list2
相同的对象的引用,您分配给list2
的第二个list1
对象就会变为垃圾。
答案 1 :(得分:1)
简单解释一下:
Java使用引用语义。在这种情况下,对于list2 = list1之后的同一对象,您有两个名称(list1,list2)。
C ++使用值语义。 list1的值被复制到list2,你有一个新的无关对象(list2),可以在不影响复制对象(list1)的情况下进行变异。
答案 2 :(得分:1)
在C ++中使用相同行为的最简单方法是将list2声明为引用 - 但是,这要求赋值发生在list2的声明中,而不是在以下之后:
vector<int> &list2 = list1;