[英]Is using a complex function in initializer list to initialize const member a good design?
recently I was looking at old horrible mess of a class... Long story short it would help with thread safety if one member was const. 最近我看着一个班级的老混乱...长话短说,如果一个成员是常设,它将有助于线程安全。
But the problem is that member is initialized in ctor, and it is nontrivial construction. 但问题是成员是在ctor中初始化的,而且是非常重要的构造。 So I was thinking about creating a special init function for that member. 所以我在考虑为该成员创建一个特殊的init函数。 Is that a good decision. 这是一个很好的决定。 Small super simple example(real code is full of conditionals :) and try-s) : 小超级简单的例子(真正的代码充满了条件:)和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;
}
};
This is actually a common and accepted solution to this problem. 这实际上是解决此问题的常见解决方案。 If possible, consider making the init function static, so that unexpected semantics of operations on object under construction (such as behaviour of virtual calls) can't kick in. 如果可能,请考虑使init函数保持静态,以便对正在构造的对象(例如虚拟调用的行为)的操作的意外语义无法启动。
Late to the party, but to add for any new search-engine'ers: 晚会,但添加任何新的搜索引擎:
If init_pair
isn't going to be used anywhere else I find a lambda to be the most elegant way of solving this problem: 如果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;
}
};
To initialize a const data member the only way is to initialize it in member initializer list
. 要初始化const数据成员,唯一的方法是在member initializer list
初始化它。
p
is a const, so it can be initialized to a value, but it can't be assigned a value. p
是一个const,因此可以将其初始化为一个值,但不能为其赋值。 Conceptually, calling a constructor creates an object before the code within the brackets is executed. 从概念上讲,调用构造函数会在执行括号内的代码之前创建一个对象。 Thus calling ComplexInitList(int a, int b):p(init_pair(a,b))
cause the program first to allocate space for member p
. 因此, calling ComplexInitList(int a, int b):p(init_pair(a,b))
会导致程序首先为成员p
分配空间。
Then program flow enters the brackets and uses ordinary assignment to place values into the allocated space. 然后程序流进入括号并使用普通赋值将值放入分配的空间。 So if you want to initialize a const data member, you have to initialize it in member initializer list
因此,如果要初始化const数据成员,则必须在member initializer list
初始化它
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.