在构造函数中初始化 <random> 类 会导致段错误
Initializing <random> classes in constructor causes segfault
在下面的代码中,RandomCharSource
应该根据请求简单地 return 一个随机字符。它的构造函数正在初始化 mt19937
、uniform_int_distribution<int>
和 random_device
。但是,当我实例化我的对象时,出现段错误。
当我在下面的 bar()
函数中手动创建这些随机 类 时,它工作正常。
我做错了什么?这里有初始化顺序问题吗?我正在使用 GCC 4.7.3。
#include <random>
#include <iostream>
class RandomCharSource
{
public:
explicit RandomCharSource() : _re{_rd()}, _dist{0, 255} {};
inline char get_next_char() { return _dist(_re); };
private:
std::mt19937 _re;
std::uniform_int_distribution<int> _dist;
std::random_device _rd;
};
void foo()
{
RandomCharSource s;
std::cout << s.get_next_char() << std::endl;
}
void bar()
{
std::random_device _rd;
std::mt19937 _re{_rd()};
std::uniform_int_distribution<int> _dist{0,255};
std::cout << (char)_dist(_re) << std::endl;
}
int main()
{
bar(); // Works OK
foo(); // Segfault
return 0;
}
是因为你的初始化顺序
class RandomCharSource
{
public:
explicit RandomCharSource() : _re{_rd()}, _dist{0, 255} {};
inline char get_next_char() { return _dist(_re); };
private:
std::mt19937 _re;
std::uniform_int_distribution<int> _dist;
std::random_device _rd;
};
您需要 _rd
在 _re
之前。成员按照它们在 class 中声明的顺序进行初始化。因此,当您尝试使用 _rd
初始化 _re
时,_rd
尚未初始化。
来自标准 §12.6.2.13
(强调我的)
In a non-delegating constructor, initialization proceeds in the following order:
13.1 — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
13.2 — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
13.3 — Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
13.4 — Finally, the compound-statement of the constructor body is executed.
[Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. —end note]
在下面的代码中,RandomCharSource
应该根据请求简单地 return 一个随机字符。它的构造函数正在初始化 mt19937
、uniform_int_distribution<int>
和 random_device
。但是,当我实例化我的对象时,出现段错误。
当我在下面的 bar()
函数中手动创建这些随机 类 时,它工作正常。
我做错了什么?这里有初始化顺序问题吗?我正在使用 GCC 4.7.3。
#include <random>
#include <iostream>
class RandomCharSource
{
public:
explicit RandomCharSource() : _re{_rd()}, _dist{0, 255} {};
inline char get_next_char() { return _dist(_re); };
private:
std::mt19937 _re;
std::uniform_int_distribution<int> _dist;
std::random_device _rd;
};
void foo()
{
RandomCharSource s;
std::cout << s.get_next_char() << std::endl;
}
void bar()
{
std::random_device _rd;
std::mt19937 _re{_rd()};
std::uniform_int_distribution<int> _dist{0,255};
std::cout << (char)_dist(_re) << std::endl;
}
int main()
{
bar(); // Works OK
foo(); // Segfault
return 0;
}
是因为你的初始化顺序
class RandomCharSource
{
public:
explicit RandomCharSource() : _re{_rd()}, _dist{0, 255} {};
inline char get_next_char() { return _dist(_re); };
private:
std::mt19937 _re;
std::uniform_int_distribution<int> _dist;
std::random_device _rd;
};
您需要 _rd
在 _re
之前。成员按照它们在 class 中声明的顺序进行初始化。因此,当您尝试使用 _rd
初始化 _re
时,_rd
尚未初始化。
来自标准 §12.6.2.13
(强调我的)
In a non-delegating constructor, initialization proceeds in the following order:
13.1 — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
13.2 — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
13.3 — Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
13.4 — Finally, the compound-statement of the constructor body is executed.
[Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. —end note]