将参数传递给 constexpr 函数

Passing arguments to constexpr functions

我是编程新手,我开始使用 使用 C++ 编程原理和实践 来学习编程。今天我来这里是因为我在理解 constexpr 函数方面遇到了一些问题。在第 8 章中,作者用几行文字和一个使用这些词的简短示例介绍了它们:

A function represents a calculation, and sometimes we want to do a calculation at compile time. The reason to want a calculation evaluated by the compiler is usually to avoid having the same calculation done millions of times at run time.

We convey our intend to have a function evaluated at compile time by declaring the function as a constexpr function. A constepxr function can be evaluated at compile time just if it is given constant expressions as arguments.

constexpr double xscale = 10; // scaling factors 
constexpr double yscale = 0.8; 
constexpr Point scale(Point p) { return { xscale*p.x, yscale*p.y }; };

Assume that point is a simple struct with members x and y representing 2D coordinates. Now, when we give scale() a Point argument, it returns a point with coordinates scaled according to the factors xscale and yscale. For example:

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 是否被视为常量表达式? 如果是,为什么?

数据成员xy可以被认为是常量表达式吗?

我的书没有提供太多信息,所以我在这个概念上遇到了一些问题。

基本上,constexpr 函数可以在编译时或 运行 时执行,具体取决于上下文。只有当它的所有参数都是 constexpr 并且它的结果在需要 constexpr 的上下文中使用时(例如,分配给 constexpr 值,模板参数,或者说,c 风格的数组大小)。否则,它会在 运行 时像任何其他函数一样被评估。因此 p3p4 行在 运行 时执行,而 p5 给出错误,因为 scale(p1) 不是 constexpr,实际上 p6 也应该给你一个错误,除非你在 p2 的定义中添加 constexpr。请参阅示例 here

为什么我们可以使用 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(),可以有任何值,只能在 运行 时间知道,因此错误。

在我看来,它在书中有问题。看起来应该是

constexpr Point p2{10,10};

只有在这种情况下,任何现代编译器都不会 error on call

constexpr Point p6 = scale(p2); // p6 == {100,8};

那是因为你试图用函数的结果初始化 constexpr 变量,这将在运行时计算(如果 p2 未声明 [​​=12=])。