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

Deleted function error after using random lib in struct

提问人:zarro 提问时间:3/26/2022 更新时间:3/26/2022 访问量:279

问:

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

错误 C2280 “RandNormGen::RandNormGen(const RandNormGen &)”: 尝试引用已删除的函数

我不完全明白这意味着什么或该怎么做,但我想我把它缩小到与 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;
    }
};

任何帮助或见解将不胜感激!

C++ 随机 结构 std deleted-functions

评论

0赞 Tim Roberts 3/26/2022
什么语句触发了此错误?它抱怨复制构造函数。
0赞 Retired Ninja 3/26/2022
如果我填空,它可以工作: ideone.com/dhe5sd 一个最小的可重现示例怎么样,这样我们就可以看到您是如何填写空白来演示问题的?
0赞 Ted Lyngmo 3/26/2022
您正在尝试复制它 - 不要使用RandNormGen::RandNormGen(const RandNormGen &)

答:

6赞 user17732522 3/26/2022 #1

std::random_device不可复制或移动。因此,您的类也无法复制或移动。

但是,保留实例实际上没有任何意义。你(希望)只用它来播种实际的随机数生成器。因此,将其从结构中删除,而是在构造函数中: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;
    }
};

(的默认构造函数 already 初始化为 和 but 的分布参数。std::normal_distribution01std::normal_distribution<float> normalDist{0, 1};


但是,首先要注意您正在执行的操作导致了对复制构造函数的要求。

如果实际复制而不是移动类对象,则最终将得到两个具有相同随机数生成器状态的类实例,这意味着副本中生成的随机数与原始生成的随机数没有区别。

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

RandNormGen() = default;

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

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

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


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

评论

0赞 zarro 3/26/2022
由于某种原因,我无法在干净的项目中重现错误,但是从结构中删除 std::random_device 确实可以解决所有问题。谢谢你让我更好地理解随机库,我今天才刚刚开始使用它,所以我还在弄清楚事情。
0赞 zarro 3/26/2022
ps:我制作这个结构的原因是为了我可以轻松地将指向它的指针传递给其他函数和类,以便它们可以使用它。