我有一个整数 vector ,想随机访问它的一个元素。这是一个最小的例子:
#include <iostream>
#include <random>
#include <vector>
class Random
{
private:
const int N = 8;
std::vector<int> data;
std::mt19937 randomGenerator;
public:
void Reset(int seed = 0) {
data.resize(N + 1);
if(seed) { this->randomGenerator.seed(seed); }
}
void UpdateVector(int delta) {
std::uniform_int_distribution<int> uniformBuffer(1, N);
/*unsigned*/ int randomIndex = uniformBuffer( randomGenerator );
data[randomIndex] += delta;
}
};
int main() {
Random rnd;
rnd.Reset();
rnd.UpdateVector(1);
return 0;
}
这在 Microsoft Visual C++ 2017 的 Debug模式下完美运行。但是当我在 Release模式下运行该程序时,它因访问冲突而崩溃。快速查看生成的汇编代码会发现一些神奇的事情发生了,其中 int
索引被扩展(带符号)到 size_t
,然后是一个奇怪的值(我认为添加了 0xffff0004
) - 这确实不再是有效索引了!
我设法通过取消注释 randomIndex
声明中的 'unsigned' 修饰符来修复这个错误,但我很好奇为什么。这是我正在使用的编译器中的错误(快速搜索没有发现任何合理的东西)还是我有误解?
最佳答案
在调查您之前的 question昨天,它已关闭,您在将其重新发布到此处之前将其删除,问题是 Microsoft 64 位代码优化器的错误。
从 uniform_int_distribution<int>
中获取结果时并将其作为 size_t
传递 vector 的值 operator[]
,内部用于“将有符号范围转换为无符号范围,反之亦然”的调整因子保留在分布类之外,并针对数组访问进行缩放,从而导致问题。奇怪的是,将结果转换为 size_t
时不会发生这种情况。用于展示。
这个示例演示了这个问题。
#include <vector>
#include <random>
#include <iostream>
#include <iomanip>
const int N = 8;
std::mt19937 randomGenerator;
class tester {
public:
int operator[](size_t idx) const {
std::cout << "Offset is " << std::hex << idx << "\n";
return int(idx);
}
};
int main() {
std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8};
std::uniform_int_distribution<int> uniformBuffer(1, N);
std::cout << "Number " << size_t(uniformBuffer(randomGenerator)) << "\n";
tester t;
std::cout << "Index " << v[t[uniformBuffer(randomGenerator)]] << "\n";
}
使用 64 位编译器,使用 cl /W4 /MD /EHsc /Ox
编译输出是
Number 5
Offset is ffffffff00000007
Index 7
v
的使用是必要的。如果省略,则传递给 tester
的偏移量是 7.
关于c++ - 访问随机 vector 元素时发生访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49266674/