何时应该在C++中使用文字类?

TGO*_*TGO 11 c++ class constexpr c++11

有人能告诉我什么时候需要C++中的文字类? 我对constexpr构造函数,constexpr成员有点困惑,我看不出有什么意义.我想看看它的一些实际用途.

另外我想知道set成员函数是否需要constexpr,即:

constexpr void set_num(int a) { num = a; }
Run Code Online (Sandbox Code Playgroud)

Jon*_*ely 11

在C++ 03中,该对象具有动态初始化

struct Data {
  int i;
  int j;
};
Data init_data();  // calculate something
const Data data = init_data();
Run Code Online (Sandbox Code Playgroud)

即,当程序启动时,在main运行之前,将调用该函数并初始化该对象.

在C++ 11中,对象可以具有常量初始化,这是一种静态初始化形式,这意味着它的值在编译时设置,并在程序开始之前初始化.这有助于避免静态初始化顺序惨败等.为了确保类型获得常量初始化,必须通过常量表达式初始化,因此必须有一个constexpr构造函数,并且在完整表达式中调用的任何函数都必须是constexpr函数.

类型Data是微不足道的,因此它的隐式声明的构造函数是constexpr构造函数,因此要使全局data进行常量初始化,我们只需要init_data()成为一个constexpr函数:

struct Data {
  int i;
  int j;
};
constexpr Data init_data();  // calculate something
constexpr Data data = init_data();
Run Code Online (Sandbox Code Playgroud)

文字类型的优点是这些类型可以用在其他常量表达式中,即在需要编译时常量的上下文中.所以现在我们将data对象作为编译时常量,我们可以在其他常量表达式中使用它,例如初始化其他编译时常量:

const int i = ::data.i;
Run Code Online (Sandbox Code Playgroud)

我们可以将Data类型用于具有类内初始值设定项的静态数据成员:

struct MoreData {
  static constexpr Data zerozero = Data{};  // OK, Data is a literal type
};
Run Code Online (Sandbox Code Playgroud)

如果Data不是文字类型,我们将不得不写:

struct MoreData {
  static const Data zerozero;
};

// in moredata.cc
const Data MoreData::zerozero = Data{};
Run Code Online (Sandbox Code Playgroud)

然后只看到标题的代码不知道它的值,MoreData::zerozero并且不能在编译时优化中使用它.

因此,"文字类型"规则的优点是它们允许您定义可以在常量表达式中使用的新类类型.在C++ 03中,只有极少数类型(如整数)可用于常量表达式,例如整数文字,10x23整数类型的编译时常量.在C++ 11中,您可以编写自己的类型,这些类型在构造函数中可以具有中等复杂的逻辑(可以在constexpr函数中表示的任何东西),但仍可以用作编译时常量.

另外我想知道set成员函数是否需要constexpr,即

constexpr成员函数是一个的一种特殊情况const的成员函数,所以它不能修改(非-mutable类型的)的成员.修改对象的setter函数不能是const.

要成为文字类型,类必须遵循一些规则,包括至少有一个constexpr构造函数.这并不意味着该类型的所有对象都必须constexpr常量,它只是意味着如果它们被声明为这样并且使用类的构造函数之一初始化,那么该类型的对象可以constexpr常量constexpr.要Data再次使用该示例,程序中的大多数对象将不是常量:

Data d = { 0, 1 };
d.i = d.i + 5;
Run Code Online (Sandbox Code Playgroud)

因此,如果您添加了一个setter,一个修改该对象的函数,那么只有在该类型的非const对象上使用它才有意义,并且像修改该类型的任何其他函数一样,它不应该是


bil*_*llz 5

constexpr修复了使用数字限制时C++ 98中的问题.在C++ 11之前的一个表达式如

std::numeric_limits<short>::max()
Run Code Online (Sandbox Code Playgroud)

不能用作整数常数,尽管它几乎等于宏INT_MAX.使用C++ 11,这样的表达式被声明为constexpr,因此,例如,您可以使用它来声明数组编译时计算(元编程):

std::array<float,std::numeric_limits<short>::max()> a;
Run Code Online (Sandbox Code Playgroud)