获取std :: vector的总和是使用引用而不是值?

时间:2012-02-13 02:38:15

标签: c++

我有一个包含整数值的向量,我希望求和。然而,它总计错误 - 如果向量在-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;

产生以下输出:Temp total: 18446744073709551603

当我逐步完成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

我很确定我正在添加内存位置而不是内存位置中的值 - 我可能错了 - 但我不确定为什么我不在{{1}添加值}}。当我使用X[i]中的值填充X时,它们是readings[i].x s,然后我将其输入到double s。这是我的错误吗?检查GDB时,int值的类型转换应该是int,或者至少是某种类型的数据:

readings[i].x

我很难过;如果有人能说明为什么我没有添加我认为我正在添加的内容,我将不胜感激。

EDIT
这是从(gdb) p (int)readings[i].x $1 = -1 int的投射。我把它翻过来,按下“提交问题”并发现我的错误。虽然,我仍然不明白为什么它正在做它正在做的事情 - 任何关于它的光线都会很精彩 - 为什么,如果我在unsigned long添加int ,它不接受unsigned long的值吗?

3 个答案:

答案 0 :(得分:4)

这是因为您的temptotal未签名。添加到其中的所有数字都是解释为无符号,因此小负数会成为two's complement representation中的大正数。

答案 1 :(得分:2)

不,你距离你的unsigned long只有1分,它正在包裹着。

另外,请使用std::accumulate

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

答案 2 :(得分:2)

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

unsigned int的简单情况下,您可以将任何数字视为二进制数的直接表示,即

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

每个数字都存储在一些有限的内存中,而int通常是32位(或4个字节)。这意味着上面表示左侧的所有位都是零。

然而,int已签名,因此必须将信息存储在某处。碰巧是Twos complement是二进制中有符号整数的方便二进制表示(读取它)。对int s

来说意味着什么
0 = 0b0
-1 = 0b11111111111111111111111111111111 (32 bits of all ones)

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