gpt4 book ai didi

c++ - gcc 如何优化这个循环?

转载 作者:可可西里 更新时间:2023-11-01 17:55:30 24 4
gpt4 key购买 nike

所以我遇到了一些奇怪的行为,我将其简化为以下最小示例:

#include <iostream>
#include <vector>

int main()
{
std::vector<int> vec;

for(int i = 0; i < 1000; i++)
{
vec.push_back(2150000 * i);
if(i % 100 == 0) std::cout << i << std::endl;
}
}

使用gcc 7.3.0编译时使用命令

c++ -Wall -O2 program.cpp -o program

我没有收到任何警告。运行该程序会产生以下输出:

0
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300

[ snip several thousand lines of output ]

1073741600
1073741700
1073741800
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)

我猜这意味着我终于用完了 vector 的内存。

显然这里有问题。我想这与 2150000 * 1000 略大于 2^31 这一事实有关,但它并不那么简单——如果我将这个数字减少到 2149000,那么程序会按预期运行:

0
100
200
300
400
500
600
700
800
900

cout 不是重现此行为所必需的,所以我想实际上是一个最小的例子

#include <vector>

int main()
{
std::vector<int> vec;

for(int i = 0; i < 1000; i++)
{
vec.push_back(2150000 * i);
}
}

运行它会导致程序等待很长时间然后崩溃。

问题

我对 C++ 在任何严重级别上都相当陌生。我在这里做的是不是允许未定义行为的愚蠢行为,如果是这样,那是什么?或者这是 gcc 中的错误?

我确实尝试用谷歌搜索这个,但我真的不知道用谷歌搜索什么。

附录

我看到(有符号的)整数溢出在 C++ 中是未定义的行为。据我了解,这仅意味着表达式的行为

21500000 * i

是未定义的——即它可以计算为任意数字。也就是说,我们可以看到这个表达式至少没有改变 i 的值。

最佳答案

为了回答我自己的问题,在检查汇编器输出后,g++ 似乎通过更改优化了这个循环

for(int i = 0; i < 1000; i++)
{
vec.push_back(2150000 * i);
}

类似于

for(int j = 0; j < 1000 * 2150000; j += 2150000)
{
vec.push_back(j);
}

我猜加法比每个循环执行乘法更快,关于溢出是未定义行为的规则意味着可以进行此更改而无需担心如果计算溢出是否会引入意外行为。

当然,优化循环中的条件总是失败,所以最终我得到的结果更像是

for(int j = 0; true; j += 2150000)
{
vec.push_back(j);
}

关于c++ - gcc 如何优化这个循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52839728/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com