在结构中使用随机库后删除函数错误

Deleted function error after using random lib in struct

我正在尝试围绕标准随机数生成器编写一个简单的结构。根据编译器,我可以初始化这个 class 但是当我尝试使用该函数时它会出现以下错误:

Error C2280 'RandNormGen::RandNormGen(const RandNormGen &)': attempting to reference a deleted function

我不完全理解这意味着什么或如何处理它,但我想我将其缩小到与 std::random_device rd; 相关的范围;

这是我的结构:

struct RandNormGen {
    std::random_device rd;
    std::mt19937 gen;
    std::normal_distribution<float> normalDist;

    RandNormGen() {
        gen = std::mt19937(rd());
        normalDist = std::normal_distribution<float>(0, 1);
    }

    float randFloat(float sigma, float mean = 0) {
        float r = normalDist(gen) * sigma + mean;
        return r;
    }
};

如有任何帮助或见解,我们将不胜感激!

std::random_device 不可复制或移动。所以你的class也不能被复制或移动。

但是,保留 std::random_device 实例实际上没有任何意义。您(希望)仅使用它来播种实际的随机数生成器。所以从结构中移除它,而不是在构造函数中:

gen = std::mt19937(std::random_device{}());

或者完全跳过构造函数并使用默认成员初始化器,因为您的默认构造函数除了初始化成员外什么都不做:

struct RandNormGen {
    std::mt19937 gen{std::random_device{}()};
    std::normal_distribution<float> normalDist;

    float randFloat(float sigma, float mean = 0) {
        float r = normalDist(gen) * sigma + mean;
        return r;
    }
};

std::normal_distribution 的默认构造函数已经将分布参数初始化为 01,但 std::normal_distribution<float> normalDist{0, 1}; 也可以。)


但是请注意您正在做的事情首先导致了对复制构造函数的要求。

如果您实际上 复制 而不是 移动 class 对象,您将得到两个 class与随机数生成器的状态相同,意味着副本中生成的随机数不会与原始生成的随机数不同。

如果这不是您想要的行为,您可以显式删除复制构造函数,以便只允许移动:

RandNormGen() = default;

RandNormGen(const RandNormGen&) = delete;
RandNormGen(RandNormGen&&) = default;

RandNormGen& operator=(const RandNormGen&) = delete;
RandNormGen& operator=(RandNormGen&&) = default;

或者您可以定义具有预期语义的复制构造函数和赋值运算符(例如重新播种生成器)。


更一般地说,考虑将随机数生成器移出 class。为每个对象设置一个随机生成器通常没有任何意义。通常在程序中每个线程有一个生成器就足够了。