C++ 在初始值设定项列表中使用复杂函数初始化常量成员是一种好的设计吗?

C++ 在初始值设定项列表中使用复杂函数初始化常量成员是一种好的设计吗?,c++,constructor,C++,Constructor,最近我在看一个旧的糟糕的班级。。。 长话短说,如果一个成员是const,它将有助于线程安全。 但问题是成员是在ctor中初始化的,这是一个非平凡的构造。所以我想为这个成员创建一个特殊的init函数。这是个好决定吗。 小型超级简单示例(实际代码中充满了条件:)和try-s) : 类复杂度列表 { std::pair init_pair(常量int第一,常量int第二) { 如果((第一个==0)| |(第二个==0)) throw std::无效的_参数(“div by 0”); 返回std::m

最近我在看一个旧的糟糕的班级。。。 长话短说,如果一个成员是const,它将有助于线程安全。
但问题是成员是在ctor中初始化的,这是一个非平凡的构造。所以我想为这个成员创建一个特殊的init函数。这是个好决定吗。 小型超级简单示例(实际代码中充满了条件:)和try-s) :

类复杂度列表
{
std::pair init_pair(常量int第一,常量int第二)
{
如果((第一个==0)| |(第二个==0))
throw std::无效的_参数(“div by 0”);
返回std::make_对(1.0/第一,1.0/秒);
}
常数std::对p;
公众:
复杂元素表(inta,intb):p(init_对(a,b))
{

Std::CUT

这实际上是这个问题的一个常见的和可接受的解决方案。如果可能的话,考虑使init函数静态化,以便对正在构建的对象(如虚拟调用的行为)的操作的意想不到的语义。无法启动。

要初始化常量数据成员,唯一的方法是在
成员初始值设定项列表中初始化它

p
是一个常量,因此可以将其初始化为一个值,但不能为其赋值。从概念上讲,调用构造函数会在代码之前创建一个对象 因此,
调用ComplexInitList(inta,intb):p(init_pair(a,b))
使程序首先为成员
p
分配空间

然后程序流进入
括号和使用普通赋值将值放入分配的空间。因此,如果要初始化常量数据成员,必须在晚到参与方的
成员初始值设定项列表中对其进行初始化,但要为任何新的搜索引擎添加:

如果
init\u pair
不打算在其他任何地方使用,我发现lambda是解决此问题的最优雅的方法:

类复杂度列表
{
常数std::对p;
公众:
复杂元素列表(常数内部a、常数内部b):
p([](常数内部a,常数内部b){
如果((第一个==0)| |(第二个==0)){
throw std::无效的_参数(“div by 0”);
}
返回std::make_对(1.0/第一,1.0/秒);

}())//成员是否为常量对线程安全没有影响;唯一的问题是您是否修改它。(但是,IMHO,您的解决方案仍然有意义。)如果是常量,您可以在不使用互斥锁的情况下读取它(在C++11中)@NoSensetal:如果它是非常量,只要它没有被修改,你就可以在没有互斥锁的情况下读取它。
const
告诉编译器帮助确保它没有被修改。请注意,即使它是
const
,如果对象是在一个线程中创建的,然后从另一个线程访问,你也不能不按顺序读取它。这是j你只需要对一对操作进行排序(创建和读取),而如果有对非常量对象的写入,它们也需要对读取进行排序。是的,我知道,但tnx很好地解释了这一点……我在帖子中说的是正确的,但并不精确:“如果一个成员是const,它将有助于线程安全”应该是:“这将使线程安全设计更容易,因为在初始化之后,在const memeber上您不需要互斥体”。Ofc如果您执行ComplexInitList*ptr=new ComplexInitList();而其他一些线程正在执行dumb spin wait(而ptr==0{}//使用ptr),则存在竞争条件
class ComplexInitList
{
std::pair<double,double> init_pair(const int first, const int second)
{
    if ((first == 0) || (second == 0))
       throw std::invalid_argument("div by 0");
    return std::make_pair(1.0/first, 1.0/second);
}
const std::pair<double,double> p;
public:
 ComplexInitList(int a, int b):p(init_pair(a,b))
{
    std::cout << p.first << ", " << p.second << std::endl;
}  
};