我有一个包含许多结构的全局二维数组。从函数内部我尝试改变它的成员:
struct ControlPin {
int pin;
int previousValue;
};
ControlPin controls[CHANNELS][MULTIPLEXERS];
void readControlInput(int channel, int multiplexer) {
ControlPin control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
}
如果我在readControlInput()中打印出control.previousValue,我可以验证它是否已经更改,但是在退出函数范围后,更改就消失了。如何获取对结构的引用而不是复制它?我认为这就是发生的事情,但我不明白为什么。我知道当你将一个值作为参数传递给一个函数时,它实际上是一个副本,但是我在这里直接访问全局数组?
我已经习惯了Java,所以这对我来说有点混乱。
答案 0 :(得分:4)
在Java中,所有对象都是(IIRC)引用。在C ++中,默认情况下对象是值。当你这样做
ControlPin control = controls[channel][multiplexer];
你复制 controls[channel][multiplexer]
中的“值”,然后修改control
时只修改本地值,而不是数组中的值。
最简单的选择是在声明变量时使用&符号(control
)明确表示&
是引用:
ControlPin& control = controls[channel][multiplexer];
// ^
// |
// Note ampersand here
告诉编译器control
是引用,然后将其初始化为引用controls[channel][multiplexer]
处的对象(值)。
在不相关的情况下,C ++没有边界检查。如果您访问数组超出范围,编译器将很乐意允许它,但它将在运行时导致未定义的行为。如果你想避免奇怪的问题,你需要自己做边界检查。它不一定在函数中,但它需要在某个地方完成。
答案 1 :(得分:1)
你没有直接访问数组,这就像你将元素传递给函数一样:
void readInput(ControlPin control)
{
control.previousValue = analogRead(control.pin);
}
void readControlInput(int channel, int multiplexer) {
readInput(controls[channel][multiplexer]);
}
您可以从类型中了解 - ControlPin
表示相同的事情,无论它是局部变量还是参数。
在C ++中,包含类实例的变量总是包含类实例而不是它们的某种“引用”,所以就像调用函数一样,
ControlPin control = controls[channel][multiplexer];
创建数组元素的副本,并
control.previousValue = analogRead(control.pin);
修改该副本。
最简单的解决方法是将其写在一行:
controls[channel][multiplexer].previousValue = analogRead(control.pin);
您还可以使用引用变量(与Java的“引用”不同)来引用数组元素本身:
ControlPin& control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
如果您需要使用相同的元素执行多个操作,这将非常有用 - 与重复索引相比,它更易读,更容易出错。