14

有人可以告诉我C++什么时候需要文字类吗?我对constexpr构造函数和 constexpr 成员 感到有些困惑,我看不出重点是什么。我想看看它的一些实际用途。

另外我想知道一个集合成员函数是否需要是constexpr,即:

constexpr void set_num(int a) { num = a; }
4

3 回答 3

12

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

struct Data {
  int i;
  int j;
};
Data init_data();  // calculate something
const Data data = init_data();

即当程序启动时,在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();

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

const int i = ::data.i;

我们可以将Data类型用于具有类内初始化程序的静态数据成员:

struct MoreData {
  static constexpr Data zerozero = Data{};  // OK, Data is a literal type
};

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

struct MoreData {
  static const Data zerozero;
};

// in moredata.cc
const Data MoreData::zerozero = Data{};

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

所以“文字类型”规则的优点是它们允许您定义可以在常量表达式中使用的新类类型。在 C++03 中,只有极少数类型(例如整数)可以用于常量表达式,例如整数字面量,例如1or0x23或整数类型的编译时常量。在 C++11 中,您可以编写自己的类型,这些类型在其构造函数中具有中等复杂的逻辑(可以在constexpr函数中表示的任何内容),但仍可用作编译时常量。

另外我想知道一个集合成员函数是否需要是 constexpr,即

constexpr成员函数是成员函数的一种特殊情况,const因此它不能修改-mutable该类型的(非)成员。修改对象的 setter 函数不能是 const。

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

Data d = { 0, 1 };
d.i = d.i + 5;

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

于 2013-01-14T01:01:22.480 回答
7

constexpr 修复了 C++98 中使用数值限制时的问题。在 C++11 之前的表达式,例如

std::numeric_limits<short>::max()

不能用作积分常数,虽然它几乎等于宏INT_MAX。对于 C++11,这样的表达式被声明为 constexpr,例如,您可以使用它来声明数组编译时计算(元编程)

std::array<float,std::numeric_limits<short>::max()> a;
于 2013-01-13T23:28:37.027 回答
3

类的一大优势constexpr是可以将它们放入 .ro 数据中,这可以减少可执行文件的大小并提高性能。特别是。对于几何类型,例如或类似的“简单”类型,这非常简洁,因为您也可以摆脱“魔术”数字。参见例如https://www.kdab.com/kdab-contributions-to-qt-5-0-part-4/

于 2013-01-14T00:18:14.617 回答