访问随机向量元素

时间:2018-03-13 22:13:11

标签: c++

我有一个整数向量,想要随机访问其中一个元素。这是一个最小的例子:

#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中的调试模式下完美运行。但是当我在发布模式下运行程序时,它会因访问冲突而崩溃。快速查看生成的汇编代码会显示一些神奇的事情,其中​​int索引被扩展(带有符号)到size_t,然后是一个奇怪的值(我认为它是{{1} })被添加 - 这确实不再是一个有效的索引!

我设法通过取消注释未签名的&#39;来修复错误。 0xffff0004声明中的修饰语,但我很好奇为什么。这是我使用的编译器中的一个错误(快速搜索没有发现任何可能的错误)或者我是否存在误解?

1 个答案:

答案 0 :(得分:2)

在昨天调查您之前的question时,它已关闭并且您在此处重新发布之前将其删除,问题是Microsoft优化器对64位代码的错误。

uniform_int_distribution<int>获取结果并将其作为size_t值传递给向量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。