在结构中使用随机库后删除函数错误
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
的默认构造函数已经将分布参数初始化为 0
和 1
,但 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。为每个对象设置一个随机生成器通常没有任何意义。通常在程序中每个线程有一个生成器就足够了。
我正在尝试围绕标准随机数生成器编写一个简单的结构。根据编译器,我可以初始化这个 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
的默认构造函数已经将分布参数初始化为 0
和 1
,但 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。为每个对象设置一个随机生成器通常没有任何意义。通常在程序中每个线程有一个生成器就足够了。