如何初始化需要执行计算的const成员?

Rei*_*ani 18 c++ constructor const class

我理解为一堂课

class A { 
     const int myint;
  public:
     A (const int yourint);
     A (const std::string yourstring);
};
Run Code Online (Sandbox Code Playgroud)

我可以myint在初始化列表中初始化,如下所示:

A::A (const int yourint) : myint (yourint) {};
Run Code Online (Sandbox Code Playgroud)

但是,myint如果计算它所需的数据来自字符串并且可能涉及计算,那么从第二个构造函数初始化的正确方法是什么?

Log*_*uff 16

在委托(如果可用,不是必需的话)构造函数的成员初始化列表中使用函数调用:

A::A(std::string const& yourstring) : A(compute_myint(yourstring)) {};
Run Code Online (Sandbox Code Playgroud)

通过std::stringconst&,不只是const,当你在它.

compute_myint 可以是非成员,静态成员,可能无法从课外访问,无论哪个最有意义.


Arn*_*rah 8

在这里,您可以使用委托构造函数,如果可以,或者您可以在ctor中进行计算.有关第二个选项,请参阅我的第二个示例 你班上的一个例子是:

选项1:委派构造函数:C++ 11转发

class A { 
     const int myint;
     static int parse_int(const std::string& string) {/*...*/}
  public:
     A (const int yourint) : myint{yourint};
     A (const std::string yourstring) : A{parse_int(yourstring)};
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,因为parse_int只计算整数,所以它可能是static,这意味着它不需要使用类实例.当然,没有要求,因为函数也可以是一个成员,(非static),虽然static更安全,因为它几乎总能保证对象的构造.

选项2:构造函数计算,非委托

此方法可用于任何C++版本.

class A { 
     const int myint;
     static int parse_int(const std::string& string) {/*...*/}
  public:
     A (const int yourint) : myint(yourint);
     A (const std::string yourstring) : my_int(parse_int(yourstring));
}
Run Code Online (Sandbox Code Playgroud)

  • 你**可以**在这里使用委托构造函数,但你不需要**委托构造函数.这种初始化始终非常简单,即使在委派构造函数之前的旧时代也是如此.只需使用计算值初始化数据成员. (4认同)

rus*_*tyx 6

只需使用成员函数.

请记住,使用static成员函数比非静态函数更安全(即不易出错),因为在调用函数时类尚未完全初始化.

class A {
  const int myint;
public:
  A(const int yourint) : myint(yourint) {}
  A(const std::string yourstring) : myint(compute(yourstring)) {}
  static int compute(std::string s) { return (int)s.length(); }
};
Run Code Online (Sandbox Code Playgroud)

  • "使用静态成员函数更安全" - 比什么**更安全?是的,我认为,比调用成员函数"更安全",但肯定不比调用执行适当计算的非成员函数"更安全". (2认同)

Que*_*tin 5

我已经多次被这个问题惹恼了,所以我开发了一个小实用程序来解决一般情况下的问题。完整代码如下:

namespace initBlock_detail {
    struct tag { };

    template <class F>
    decltype(auto) operator + (tag, F &&f) {
        return std::forward<F>(f)();
    }
}

#define initBlock \
    initBlock_detail::tag{} + [&]() -> decltype(auto)
Run Code Online (Sandbox Code Playgroud)

它的用法如下:

int const i = initBlock {
    // Any complex calculation
    // and then return the value
    return foo;
};
Run Code Online (Sandbox Code Playgroud)

在 Coliru 上现场观看

该结构类似于 Andrei Alexandrescu 的 ScopeGuard 实现,它使用中缀运算符重载和 lambda 来实现这种轻量级语法。i的类型可以推导出来,可以是引用等。其他有用的功能包括可以using namespace在 init 块中放置声明。可以使用任何可移动和/或可复制类型。