如何解决为什么用点运算符的值在C ++中没有更改?
我来自Javascript背景,并且正在使用c ++进行实验,我想在调用函数中对数组中的struct成员进行突变,如下所示。
#include<iostream>
#include<vector>
using namespace std;
typedef struct Node{
int value;
Node(int val){
this->value = val;
}
};
void changeValueByDot(Node* p,int idx){
Node n = *(p + idx);
n.value = 54;
}
void changeValueByArrow(Node* p,int idx){
Node* n = (p + idx);
n->value = 32;
};
int main(){
vector<Node> v = {
Node(1),Node(2)
};
changeValueByDot(v.data(),1);
cout<<"After changing by dot:"<<v[1].value<<endl;
changeValueByArrow(v.data(),1);
cout<<"After changing by arrow:"<<v[1].value<<endl;
return 0;
}
现在我的困惑是为什么点运算符无法进行永久更改而箭头运算符却可以进行永久更改。 我对dot的期望是首先到达位置获取节点并更改其值。我不确定该位置的节点是否正在复制并且更改是否在复制的节点中完成。
我尝试同时使用向量数组和固定大小数组来获得相同的结果。
请帮助我理解这一点。 预先感谢!
解决方法
在这一行:
Node n = *(p + idx);
变量n
是右侧节点的副本。修改n.value
不会更改右侧引用的节点。
如果您希望n
引用已取消引用的节点,请使用引用:
Node & n = *(p + idx);
// ^
现在对n
的更改将反映在对*(p + idx)
的更改中
请注意,这不是问题,
Node* n = (p + idx);
因为n
仍然是副本,它是 pointer 的副本,修改n->value
实际上会改变{{1 }}由value
指向的同一对象的成员。
Java没有对象类型的变量。 Java具有引用对象的变量。
这是因为Java gc要求对象必须存在于堆中,并且几乎永远不会放置在对象上。用C ++术语来说,Java对象变量是精美的智能指针。
void changeValueByDot(Node* p,int idx){
Node n = *(p + idx);
n.value = 54;
}
如果类型为Node
的类型n
,则此代码创建一个本地(堆栈上)对象。
大致的Java“伪代码”等效项是:
void changeValueByDot(Node p,int idx){
Node n = (p + idx).clone();
n.value = 54;
}
或
void changeValueByDot(int reference p,int idx){
int n = p;
n = 54;
}
在第一种情况下,我们使C ++中的对象的隐式复制显式化。在第二种方法中,我们使用Java不会隐式地将其转换为引用的类型。
在两种情况下,显然只有本地数据被修改。因此,C ++版本也是如此。
Java缺少对象实例变量,这意味着它不对称地对待基元和对象。另一方面,C ++对象的行为类似于基元。您可以用C ++写一个替换int
,其语义与基本int相同,但是在后台它是一个可变大小的任意精度bigint。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。