我从constexpr构造函数,constexpr成员中得到一点点混淆,我看不清楚是什么.我想看看它的一些实际用途.
另外我想知道一个set成员函数是否需要constexpr,即:
constexpr void set_num(int a) { num = a; }
解决方法
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构造函数,所以为了使全局数据经历不断的初始化,我们只需要使init_data()成为一个constexpr函数:
struct Data { int i; int j; }; constexpr Data init_data(); // calculate something constexpr Data data = init_data();
文字类型的优点在于,这些类型可以用于其他常量表达式,即在需要编译时常数的上下文中.因此,现在我们将数据对象作为编译时常量,我们可以在其他常量表达式中使用它.初始化其他编译时常数:
const int i = ::data.i;
我们可以使用数据类型为静态数据成员使用类别初始化器:
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函数中表达的内容),但仍可用作编译时常量.
Also I’d want to know if a set member function needs to be constexpr,i.e.
constexpr成员函数是一个常量成员函数的特殊情况,因此它不能修改(不可变)类型的成员.修改对象的setter函数不能是const.
要成为一个文字类型,类必须遵循一些规则,包括至少有一个constexpr构造函数.这并不意味着该类型的所有对象都必须是constexpr常量,它只是意味着该类型的对象可以是constexpr常量,如果它们被声明为这样,并且使用类“constexpr”构造函数之一进行初始化.要再次使用数据示例,程序中的大多数对象不会是常量:
Data d = { 0,1 }; d.i = d.i + 5;
所以,如果你添加了一个setter,一个修改对象的函数,那么在这种类型的非const对象上使用它就是有意义的,和任何修改类型不同的函数一样