什么是编译时已知的值
What is a value known at compile time?
我正在学习C++编程语言,在我的书中有一章向我介绍了常数的概念:
constexpr符号常量必须给定一个在编译时已知的值
编译时已知的值是什么?为什么我们需要他们?
常量表达式是指编译器可以在编译时(即程序运行之前、编译期间)对其求值的表达式。
常数表达式可用于初始化用constexpr
标记的变量(参考C++11概念)。这样的变量向编译器提供了一个提示,即它可以在编译时进行评估(这可能会节省宝贵的运行时间周期),例如
#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;
}
示例
如果你不提供一个常量表达式,编译器就不可能在编译时完成所有这些工作:
#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;
}
示例
执行编译时额外工作而不是运行时工作的好处是性能增益,因为编译后的程序可能能够使用预先计算的值,而不必每次从头开始计算。常量表达式越昂贵,程序获得的收益就越大。
编译时已知的值是什么?
我认为谈论不变的表达更有意义。常量表达式具有在编译时已知的值。粗略地说,它可能只是一个文字,另一个变量的名称(其值在编译时也是已知的),或者是一个复杂的表达式,其中包含在编译时已知值的子表达式。
引号指出,用constexpr
声明的变量的初始值设定项需要是常量表达式。特别是,表达式必须满足以下要求才能成为常量表达式;这里列出了这些。
例如
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
)。这就是所谓的假设规则。
这意味着不需要运行程序来计算常数。例如:
int num = 4;
编译器需要这些值才能将变量放在符号表中,程序可以在其中引用和使用这些值。在常量的情况下,编译器将常量符号化为不能更改的值。因此,如果您将一个常量声明为在运行时确定的东西,它将不起作用,因为如果一个常量在编译时未定义,它将保持未定义状态。我希望这是有道理的。
- 是什么原因导致它无法编译?它是声明签名还是在函数本身的实现中
- C++如果必须在编译时确定大小,std::array 有什么意义?
- Red Hat:使用<atomic>编译很好,但链接器找不到__atomic_store_16;什么库?
- 代码编译但不起作用!cmd窗口只是理想和理想,但什么也没发生
- C++中的编译时函数是什么?
- 编译以下重载<<需要什么enable_if或其他提示?
- 使用 MSVC 编译时,msdpb* 文件的正确用法是什么?
- 关于这个在 Linux 上使用 gcc 编译的程序中的 vtable,nm 告诉我什么?
- 当我在支持 avx2 的机器上编译并在另一台仅支持 avx 的机器上运行二进制文件时会发生什么?
- Boost FFT示例-编译时出错,这段代码在做什么
- 在编译时,类模板会发生什么
- 在Windows Server 2012上运行VS2019编译的应用程序需要什么?
- Arduino IDE中自定义库类的.h文件编译错误的原因是什么
- VS2015 / 2017中的TRACE宏无法编译 - 我需要包含什么?
- 有什么需要,局部静态变量在编译时分配内存?
- 如果我在库中和应用程序中编译了相同的CPP文件,会发生什么
- C++:什么时候需要重新编译?
- GCC ARM 交叉编译,像未定义的引用"__cxa_end_catch@CXXABI_1.3"这样的错误表示什么?
- gcc 什么时候编译未使用的模板代码?
- 作为库编译什么