c++ 编译时已知的值是什么?

llmtgqce  于 2022-12-24  发布在  其他
关注(0)|答案(3)|浏览(132)

我正在学习C++编程语言,书中有一章介绍了常量的概念:
必须为constexpr符号常量指定编译时已知的值
什么是编译时已知的值?为什么我们需要它们?

zpqajqem

zpqajqem1#

constant expression表示编译器可以在编译时(即在程序运行之前,编译期间)计算的表达式。
常量表达式可以用来初始化一个标记为constexprreferring to the C++11 concept)的变量。这样的变量给编译器一个提示,提示它可以在编译时求值(这样可以节省宝贵的运行时周期),例如:

#include <iostream>

constexpr int factorial(int n) // Everything here is known at compile time
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

int main(void)
{
    constexpr int f = factorial(4); // 4 is also known at compile time
    std::cout << f << std::endl;
    return 0;
}

Example
如果不提供常量表达式,编译器就不可能在编译时完成所有这些工作:

#include <iostream>

constexpr int factorial(int n) // Everything here is known at compile time
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

int main(void)
{
    int i;
    std::cin >> i;
    const int f = factorial(i); // I really can't guess this at compile time..
                                // thus it can't be marked with constexpr
    std::cout << f << std::endl;
    return 0;
}

Example
做编译时额外工作而不是运行时工作的好处是性能增益,因为编译后的程序可以使用预先计算的值,而不必每次从头开始计算。常量表达式的开销越大,程序获得的增益就越大。

7xzttuei

7xzttuei2#

编译时已知的值是什么?
我认为讨论常量表达式更有意义。常量表达式有一个在编译时已知的值。粗略地说,它可能只是一个文字,另一个变量的名称(其值在编译时也是已知的),或者是一个包含子表达式的复杂表达式,子表达式的值在编译时是已知的。
引号声明用constexpr声明的变量的初始化器必须是常量表达式。特别是,表达式必须满足常量表达式的要求;它们被列在here中。
例如

constexpr int i = 54;
constexpr float f = 684; // Compile-time conversion from int to float

constexpr int func( int i )
{
    return i*47 % 23;
}

constexpr auto value = func(i * f); // Okay; constexpr function called
                                    // with arguments that, when substituted inside,
                                    // yield constant expressions

有时一个值在编译时就已经知道了,但是根据标准,表达式不是常量。

int i = 43;
constexpr int j = reinterpret_cast<int>(i); // Shouldn't compile. (Does with GCC)

在某些情况下,编译器可能会进行常量折叠--有些值可以在编译时计算,但不必如此。

int i = 0;

for (int j = 1; j != 10; ++j)
    i += j;

return i;

只要行为保持不变,编译器就可以完全消除循环并用55初始化i(或者简单地返回55并消除i),这称为the as-if rule

6rqinv9w

6rqinv9w3#

这意味着程序不需要运行来计算常数。例如:

int num = 4;

编译器需要这些值才能将变量放入符号表中,以便程序引用和使用它们。对于常量,编译器将常量符号化为不能更改的值。因此,如果您将常量声明为在运行时确定的值,它将不起作用。因为如果一个常量在编译时是未定义的,那么它就保持未定义。

相关问题