求std::vector的和是使用引用而不是值

Taking sum of std::vector is using references instead of values?

本文关键字:引用 vector std      更新时间:2023-10-16

我有一个包含整数值的向量,我希望对其求和。然而,它的总和是错误的——如果向量保持-10到10之间的10点,那么我的总和不应该是18446744073709551602

我声明向量,并用值填充它:

std::vector<int> X;
for ( int i = 0; i < readings.size() ; ++i ) { 
    X.push_back(readings[i].x);

然后我求和并显示:

unsigned long temptotal = 0;
for ( int i = 0; i < readings.size() ; ++i ) {
    std::cout << "Value in X: " << X[i] << std::endl;
    temptotal += X[i];
}
std::cout << "Temp total: " << temptotal << std::endl;

其产生以下输出:CCD_ 2。

当我在GDB中逐步通过求和循环时(在temptotal += X[i];),我可以print X[i]:

(gdb) p X[i]
$1 = (reference) @0x100100c80: -1

添加前后打印temptotal

(gdb) p temptotal
$2 = 0
(gdb) p temptotal
$3 = 18446744073709551615

我很确定我添加的是内存位置,而不是内存位置中的值——我可能错了——但我不确定为什么不添加X[i]中的值。当我用readings[i].x中的值填充X时,它们是double s,然后我键入它强制转换为int s。这就是我的错误所在吗?检查GDB时,readings[i].x值的类型转换应该是int,或者至少是某种数字:

(gdb) p (int)readings[i].x
$1 = -1

我被难住了;如果有人能告诉我为什么不添加我认为正在添加的内容,我将不胜感激。

编辑
它是从intunsigned long的铸件。我一遍又一遍,按下"提交问题",发现了我的错误。尽管如此,我仍然不明白为什么它在做它正在做的事情——任何关于这一点的线索都会很好——为什么,如果我在unsigned long中添加int,它不从int中获取值?

这是因为您的temptotal是无符号的。所有添加到它的数字都被解释为无符号,因此在2的补码表示中,小负数变成大正数。

不,您正在从unsigned long中拿走1,它正在缠绕。

此外,使用std::accumulate:

result = std::accumulate(readings.begin(), readings.end(), 0);

您在编辑中询问了为什么会发生这种情况。这是由于内存中积分类型的二进制表示。

Temp total: 184467440737095516030的简单情况下,你可以把任何数想象成它在二进制中的直接表示,即

1 == 0b1
2 == 0b10
...
42 == 0b101010

每个数字都存储在一定数量的内存中,对于int,通常是32位(或4字节)。这意味着以上表示左边的所有位都是零。

然而,int是有符号的,因此信息必须存储在某个地方。恰好Twos补码是二进制中有符号整数的一种方便的二进制表示(请阅读)。这意味着对于int

0 = 0b0
-1 = 0b11111111111111111111111111111111 (32 bits of all ones)

正如您现在可能意识到的那样,当您将int转换为unsigned int而不是负数时,由于这些数字的二进制表示,您会得到一个非常大的正数。一般来说,除非你知道自己在做什么,否则你不想在计算中混合使用无符号整数和有符号整数。