4

最近我在看一个班级的旧的可怕混乱......长话短说,如果一个成员是 const,它将有助于线程安全。
但问题是成员是在 ctor 中初始化的,而且它是非平凡的构造。所以我正在考虑为该成员创建一个特殊的 init 函数。这是一个好的决定吗。超级简单的小例子(真正的代码充满了条件:)和try-s):

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;
}  
};
4

3 回答 3

4

这实际上是该问题的常见且公认的解决方案。如果可能,请考虑将 init 函数设为静态,以便对正在构建的对象的意外操作语义(例如虚拟调用的行为)无法启动。

于 2012-11-29T10:36:46.463 回答
2

迟到了,但要为任何新的搜索引擎添加:

如果init_pair不打算在其他任何地方使用,我发现 lambda 是解决这个问题的最优雅的方法:

class ComplexInitList
{
const std::pair<double,double> p;

public:
 ComplexInitList(const int a, const int b) : 
    p([](const int a, const int b) {
        if ((first == 0) || (second == 0)) {
            throw std::invalid_argument("div by 0");
        }

        return std::make_pair(1.0/first, 1.0/second);
    }()) // <-- Note the extra '()' with immediately calls the lambda!
{
    std::cout << p.first << ", " << p.second << std::endl;
} 

};
于 2015-01-15T10:10:59.713 回答
1

要初始化 const 数据成员,唯一的方法是在member initializer list.

p是一个常量,所以它可以被初始化为一个值,但它不能被赋值。从概念上讲,调用构造函数会在括号内的代码执行之前创建一个对象。从而calling ComplexInitList(int a, int b):p(init_pair(a,b))使程序首先为 member 分配空间p

然后程序流程进入括号并使用普通赋值将值放入分配的空间。所以如果你想初始化一个 const 数据成员,你必须在member initializer list

于 2012-11-29T10:42:35.453 回答