《随笔十六》—— C++中的 “ constexpr 函数、constexpr 构造函数、字面值常量类 ——C++11 ”

目录

constexpr 函数 (C++11)

constexpr 构造函数 (C++11)constexpr 构造函数



constexpr 函数 (C++11)


● constexpr 函数 是 指用于常量表达式的函数。 不过要注意的是:

函数的返回类型及所有形参的类型都得是字面值类型。(一般来说基本的数据类型、引用和指针都属于字面值类型,自定义的类、string 不属于字面值,不可以定义为constexpr。)

而且函数体中必须有且只有一条return语句。

constexpr int new_sz()
{
	return 42+10;
}
int main()
{
 
	constexpr auto foo = new_sz(); //正确:foo 是一个常量表达式
 
	cout << foo << endl;
	system("pause");
	return EXIT_SUCCESS;
}

● 说明 : 因为编译器能在程序编译时验证 new_sz() 函数返回的是常量表达式, 所以可以用 new_sz 函数 初始化 constexpr 类型的变量 foo

因执行该初始化任务时, 编译器把对 constexpr 函数的调用替换成其结果值。为了能在编译过程中随时展开, constexpr 函数被隐式地指定为内联函数。

● 注意 : constexpr 函数体内也可以包含其他语句, 只要这些语句在运行时不执行任何操作就行。 例如: constexpr 函数中可以有 空语句、类型别名 以及 using 声明.

 

● 注意 : 我们允许constexpr 函数的返回值并非一个常量。 constexpr 函数不一定返回常量表达式
 

constexpr int new_sz()
{
    return 42;
}
constexpr size_t scale(size_t cnt)
{
    return new_sz()*cnt;
}
int main()
{
    constexpr int foo = new_sz();
 
    int arr[scale(2)] = {};  //正确: scale(2) 是常量表达式
 
     int i = 2;  //i不是常量表达式
    int a2[scale(i)];   // 错误:  scale(i) 不是常量表达式
    system("pause");
    return 0; 
}

● 和 其他函数不一样, 内联函数和constexpr 函数可以在程序中多次定义。 毕竟, 编译器要想展开函数仅有函数声明是不够的, 还需要函数的定义。

不过,对于某个给定的内联函数或者constexpr 函数来说, 它的多个定义必须完全一致。

基于这个原因, 内联函数和 constexpr 函数通常定义在头文件中。
 


constexpr 构造函数 (C++11)


前面说过,constexpr 函数的返回类型及所有形参的类型都得是字面值类型。(一般来说基本的数据类型、引用和指针都属于字面值类型,自定义的类、string 不属于字面值,不可以定义为constexpr。) 不过这里有个特殊情况是,  某些自定义的类也是 字面值类型的。和其它类不同的 是, 字面值类型的类可能含有 constexpr 成员函数。  这样的成员 必须符合 constexpr 函数的所有要求, 它们是隐式的const。

数据成员都是字面值类型的聚合类是字面值常量类。如果一个类不是聚合类,但它符合下述要求,则它也是一个字面值常量类:

数据成员都必须是字面值类型。

类必须至少含有一个constexpr构造函数。

如果一个数据成员含有类内初始值,则内置类型成员的初始值必须是一条常量表达式;或者如果成员属于某种类类型,则初始值必须使用成员自己的constexpr构造函数。

类必须使用析构函数的默认定义, 该成员负责销毁类的对象(参见7.1.5节,第239页)。


constexpr 构造函数


尽管构造函数不能是const的( 参见7.1.4节,第235页), 但是字面值常量类的构造函数可以是constexpr (参见6.5.2节,第213页)函数。事实上,一个字面值常量类必须至少提供一个constexpr构造函数。

 

constexpr构造函数可以声明成 = default (参见7.1.4节,第237页)的形式(或者是删除函数的形式,我们将在13.1.6节(第449页)介绍相关知识)。

否则, constexpr沟造函数就必须既符合构造函数的要求(意味着不能包含返回语句), 又符合constexpr函数的要求 (意味着它能拥有的唯一可执行语句就是返回语句(参见6.5.2节,第214页))。综合这两点可知, constexpr构造函数体一般来说应该是空的。我们通过前置关键字 constexpr就可以声明一个constexpr构造函数了:

class Debug
{
public:
	constexpr Debug(bool b = true) :hw(b), io(b), other(b) {}
	constexpr Debug(bool h, bool i, bool o) : hw(h), io(i), other(o) {}
	constexpr  bool any() const //注意记得在尾部加上const,不然编译错误
	{
		return(hw || io || other);
	}
	void set_io(bool b)
	{
		io = b;
	}
	void set_hw(bool b)
	{
		hw = b;
	}
	void set_other(bool b)
	{
		other = b;
	}
private:
	bool hw;
	bool io;
	bool other;
};

int main()
{
    // constexpr构造函数用于生成constexpr对象以及constexpr函数的参数或返回类型

	constexpr Debug io_sub(false, true, false);

	if (io_sub.any())
	{
		//一些语句
	}

	constexpr Debug prod(false);
	if (prod.any())
	{
		//一些语句
	}
	system("pause");
	return  0;

}

constexpr构造函数必须初始化所有数据成员初始值, constexpr构造函数中或者是一条常量表达式。

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11 引入了 constexpr 关键,用于指定函数或对象是常量表达式。常量表达式是在编译时就能计算出结果的表达式,它可以用于数组大小、模板参数等需要在编译时确定的地方。 constexpr 函数 constexpr 函数是指能在编译时求值的函数,它的返回值可以作为常量表达式使用。constexpr 函数的参数和返回值必须是型。 例如,下面的函数就是一个 constexpr 函数: ```cpp constexpr int square(int x) { return x * x; } ``` 我们可以在编译时计算出 square(5) 的值,因此它是一个常量表达式。 constexpr 对象 constexpr 对象是指在编译时就能计算出值的对象。constexpr 对象必须被声明为 const,而且必须用常量表达式初始化。 例如,下面的语句定义了一个 constexpr 对象: ```cpp constexpr int max_num = 100; ``` 我们可以在编译时就知道 max_num 的值是 100,因此它是一个常量表达式。 constexpr 函数常量表达式的限制 constexpr 函数常量表达式有一些限制: 1. constexpr 函数必须有一个返回值,而且返回值必须是型。 2. constexpr 函数函数体必须足够简单,能在编译时被求值。 3. constexpr 函数不能包含任何副作用,比如修改全局变量或调用非 constexpr 函数。 4. constexpr 函数的参数和返回值必须是型。 5. constexpr 对象必须被声明为 const,而且必须用常量表达式初始化。 6. constexpr 对象的型必须是型。 总结 constexpr 关键用于指定函数或对象是常量表达式。constexpr 函数常量表达式必须在编译时就能计算出值,它们有一些限制。constexpr 函数常量表达式可以用于数组大小、模板参数等需要在编译时确定的地方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值