const和constexpr的区别?

文字:数字、字符、字符串等不能更改的值。 单引号中的是文字字符,双引号中的是文字字符。

文字值类型(literal type )算术类型、引用、指针等。

常数表达式(const experssion ):)1)值不变,)2)编译时生成计算结果的表达式。 文字是常量表达式,用常量表达式初始化的const对象也是常量表达式。

对象(或表达式)是否为常量表达式取决于其数据类型和初始值。

C 11新标准将变量声明为constexpr类型,以便编译器可以验证变量是否为常量表达式。

声明为constexpr的变量必须是常量,必须用常量表达式初始化。

应遵循的规则:函数的返回类型和所有参数的类型都是文字值类型,必须存在于函数主体中,只有一个return语句。

constexpr函数可以包含其他语句,除非在运行时执行任何操作。 例如,空语句、类型别名、using声明等)

constexpr函数隐式指定为内联函数。

a为常数式时,fun(a )为常数式。 如果a不是常数表达式,则fun(a )是常规函数。

如果constexpr函数是常量表达式,则可用于初始化constexpr变量。

),但只有0、nullptr和固定地址中的对象是用constexpr声明的指针的初始值。 因为是常数表达式。 (常数表达式定义)2)。

}

const 表示的只是这个变量不可修改,但并未限定这个变量是编译期常量还是运行期常量;而 constexpr 只能是编译期常量。

const 修饰的函数一般都是成员函数,用来表示这个函数不会对成员变量产生写操作,这点很好理解。

constexpr 修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。但是,传入的参数如果不能在编译时期计算出来,那么 constexpr 修饰的函数就和普通函数一样了,比如上面代码直接调用了 func(i)。不过,我们不必因此而写两个版本,所以如果函数体适用于 constexpr 函数的条件,可以尽量加上

}

C++中,编译时和运行时之间的边界是模糊的,这在C++14中引入泛化常量表达式时更是如此。 然而,能够操纵异构对象就意味着要能深刻理解边界的含义,让代码按自己的意图来运行。 本节的目标是使用constexpr来设置一些东西; 以了解哪些问题可以解决,哪些不能。 本节涵盖了关于常量表达式的高级概念; 只有对constexpr有很好理解的读者才应该尝试阅读。

让我们开始一个具有挑战性的问题。 下面的代码可编译吗?

答案是不能,由Clang给出的错误就像:

对出错的解释是,在f的函数体内,t不是常数表达式,因此不能用作static_assert的操作数。 原因是这样的函数根本不能由编译器生成。 要理解这个问题,考虑当我们使用具体类型实例化f模板时发生了什么:

显然,编译器不能生成f<int>的代码,如果t!= 1,它应该触发一个static_assert,因为我们还没有指定t的值。 更糟的是,生成的函数应该适用于常量和非常量表达式:

显然,不能生成fptr的代码,因为它需要能够对运行时值进行static_assert,这是没有意义的。 此外,注意,无论你是否使用constexpr函数都没关系; 使f constexpr只声明f的结果是一个常量表达式,只要它的参数是一个常量表达式,但它仍然不能让你知道你是否使用fbody中的常量表达式调用。 换句话说,我们想要的是:

在这个假设情况下,编译器将知道t是来自f的主体的常量表达式,并且可以使static_assert起作用。 然而,当前语言还不constexpr参数,并且添加它们将带来非常具有挑战性的设计和实现问题。 这个小实验的结论是参数传递剥离了constexpr-ness。 现在可能不清楚的是这种剥离的后果,接下来解释。

参数不是常量表达式意味着我们不能将其用作非类型模板参数,数组绑定,static_assert或需要常量表达式的任何其他地方。 此外,这意味着函数的返回类型不能取决于参数的值,如果你想以这样的形式得到一个新类型:

显然,这行不通。事实上,函数的返回类型只能取决于它的参数的类型,而constexpr不能改变这个事实。 但根据函数的参数返回具有不同类型的对象对我们至关重要,因为我们对操作异构对象感兴趣。 例如,一个函数可能希望在一种情况下返回类型T的对象,在另一种情况下返回类型U的对象; 从以上分析来看,我们现在知道这些“情况”将必须依赖于参数类型编码的信息,而不是它们的值。

为了通过参数传递来保留constexpr,我们必须将constexpr值编码为一个类型,然后将一个不一定是该类型的constexpr对象传递给函数。 该函数必须是模板,然后可以访问在该类型内编码的constexpr值。

TODO: 改进这个解释,并谈论包装成类型的非整数常量表达式。

让我提一个棘手的问题。 以下代码是否有效?

答案是肯定的,但原因可能不明显。 这里发生的是,我们有一个非常量的值n和一个constexpr函数f和它的引用参数。 大多数人认为它不应该工作的原因是n不是constexpr。 但是,我们不在f内部做任何事情,所以没有什么实质的理由解释它不应该工作! 这有点像在内部的一个constexpr函数:

只要throw出现的代码路径不被执行,调用的结果可以是常量表达式。 同样,我们可以在f中做任何我们想要的事,只要我们不执行需要访问它的参数n的代码,因为这不是一个常量表达式:

Clang给出的第二次调用的错误是:

让我们现在停下来看看它的游戏规则,并考虑一个更微妙的例子。 以下代码是否有效?

与我们的初始场景唯一的区别是,f现在的参数按值而不是按引用传递。 然而,这与上一个函数有所不同。 事实上,我们现在要求编译器创建一个n的副本,并将此副本传递给f。 然而,n不是constexpr,所以它的值只在运行时知道。 编译器要怎么操作编译一个变量的副本(在编译时),但该变量的值只在运行时才知道? 当然,它不能。 事实上,Clang给出的错误信息对于发生了什么很清楚:

TODO: 解释在常量表达式中不会出现副作用,即使它们产生的表达式不被访问。

}

我要回帖

更多关于 new和malloc的区别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信