有人可以告诉我 C ++ 中何时需要文字类?
我对 constexpr 构造函数,constexpr成员感到有些困惑,我看不出有什么意义。我希望看到它的一些实际用途。
此外,我想知道 set 成员函数是否需要 constexpr ,即:
constexpr void set_num(int a) { num = a; }
答案 0 :(得分:10)
在C ++ 03中,此对象具有动态初始化
struct Data {
int i;
int j;
};
Data init_data(); // calculate something
const Data data = init_data();
即。当程序启动时,在main
运行之前,将调用该函数并初始化对象。
在C ++ 11中,对象可以有常量初始化,这是静态初始化的一种形式,这意味着它的值在编译时设置并且在初始化之前被初始化程序开始了。这有助于避免static initialization order fiasco等问题。要确保类型获得常量初始化,必须通过常量表达式对其进行初始化,因此必须具有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中,只有很少的类型,例如整数,可以用在常量表达式中,例如整数文字,例如1
或0x23
或整数类型的编译时常量。在C ++ 11中,您可以编写自己的类型,这些类型在构造函数中可以具有中等复杂的逻辑(任何可以在constexpr
函数中表示的东西),但仍可以用作编译时常量。
另外我想知道一个集成员函数是否需要constexpr,即
constexpr
成员函数是const
成员函数的特例,因此无法修改该类型的(非-mutable
)成员。修改对象的setter函数不能是const。
要成为文字类型,类必须遵循一些规则,包括至少有一个constexpr
构造函数。这并不意味着该类型的所有对象必须为constexpr
常量,这只意味着该类型的对象可以是constexpr
常量它们被声明为这样,并使用类constexpr
构造函数之一进行初始化。要再次使用Data
示例,程序中的大多数对象都不是常量:
Data d = { 0, 1 };
d.i = d.i + 5;
因此,如果添加了一个setter,一个修改该对象的函数,那么只有在该类型的非const对象上使用它才有意义,并且像修改它不应该的类型的任何其他函数一样
答案 1 :(得分:5)
constexpr修复了使用数字限制时C ++ 98中的问题。在C ++ 11之前有一个表达式,如
std::numeric_limits<short>::max()
不能用作整数常量,尽管它几乎等于宏INT_MAX
。使用C ++ 11,这样的表达式被声明为constexpr,例如,
您可以使用它来声明数组或编译时计算(元编程):
std::array<float,std::numeric_limits<short>::max()> a;
答案 2 :(得分:2)
constexpr
类的一大优势是可以将它们放入.ro数据中,这可以导致可执行的大小减少和性能提升。 ESP。几何类型,例如或类似的“简单”类型,这是非常整洁,因为你也可以摆脱“魔术”数字。参见例如https://www.kdab.com/kdab-contributions-to-qt-5-0-part-4/