我是编程新手,我开始使用编程原理和使用C ++实践来学习它。今天我在这里是因为我在理解constexpr
函数时遇到了一些问题。在第8章中,作者在某些方面介绍了它们,并使用这些词语进行了简短的例子:
函数表示计算,有时我们想在编译时进行计算。希望编译器评估计算的原因通常是避免在运行时进行数百万次相同的计算。
我们通过将函数声明为
constexpr
函数来传达我们打算在编译时评估函数。可以在编译时评估constepxr
函数,只要它被赋予常量表达式作为参数。constexpr double xscale = 10; // scaling factors constexpr double yscale = 0.8; constexpr Point scale(Point p) { return { xscale*p.x, yscale*p.y }; };
假设该点是一个简单的结构,其中成员x和y代表2D坐标。现在,当我们给
scale()
一个Point
参数时,它返回一个坐标根据因子xscale
和yscale
缩放的点。例如:void user(Point p1) { Point p2{10,10}; Point p3 = scale(p1); Point p4 = scale(p2) // p4 == {100,8} constexpr Point p5 = scale(p1); // error : scale(p1) is not a constant expression constexpr Point p6 = scale(p2); // p6 == {100,8};
我的问题是:为什么我们可以使用p2
作为scale()
的参数? p2
是否被视为常量表达式?如果是,为什么?
数据成员x
和y
是否可以被视为常量表达式?
我的书中没有提供太多信息,所以我对这个概念有些疑问。
答案 0 :(得分:13)
基本上,constexpr
函数可以在编译时或运行时执行,具体取决于上下文。只有当所有参数都是constexpr
并且其结果用于需要constexpr
的上下文中时(例如赋值给constexpr
值,模板参数,或者说,保证在编译时执行) ,c风格的数组大小)。否则,它在运行时被评估为任何其他函数。因此p3
和p4
行是在运行时执行的,而p5
会出错,因为scale(p1)
不是constexpr
,实际上p6
应该除非您在constexpr
的定义中添加p2
,否则也会出现错误。查看示例here。
答案 1 :(得分:3)
为什么我们可以使用p2
作为scale()
的参数?
因为scale()
被编写为接受任何Point
或可隐式转换为Point
的内容。在这种情况下,p2
的类型为Point
。因此,它可以用作scale()
的参数。
p2被认为是一个常数表达式吗?如果是,为什么?
p2
实际上被声明为局部变量。当它用作:
constexpr Point p6 = scale(p2);
它的值是在运行时使用函数调用计算的,因此是一个错误。要使其工作,请删除constexpr
关键字。如果您希望它与constexpr
一起使用,请先将p2
声明为constexpr
。
在以下情况中:
constexpr Point p5 = scale(p1);
p1
作为参数传递给user()
,并且可以具有任何值,只能在运行时知道,因此错误。
答案 2 :(得分:3)
在我看来,这本书已经存在了。它看起来应该是
constexpr Point p2{10,10};
只有在这种情况下,任何现代编译器都不会在通话时给出error
constexpr Point p6 = scale(p2); // p6 == {100,8};
那是因为您尝试使用函数结果初始化constexpr
变量,该变量将在运行时进行评估(如果p2
未声明为constexpr
)。