C++ 中的 constexpr 是什么? [重复]

问题描述 投票:0回答:4

我对

constexpr
的概念感到非常困惑,因为我读过
constexpr
是在编译时评估的,因此与正常的
const
相比,它对于性能优化很有用。

constexpr int i = 0;
constexpr int& ri = i;

上面的代码返回错误“来自'const int'类型的表达式的'int&'类型的引用无效初始化”,为什么?

另外,接下来的代码有一个错误:

constexpr int i = 0;
constexpr int* ri = &i;

如果我将

constexpr
关键字替换为
const
,以上所有内容都可以正常工作。

c++ constants constexpr
4个回答
14
投票
constexpr int i = 0;
constexpr int  * ri = &i;

第二行是一个问题,因为指针没有指向

const
对象。指针本身是
const

使用

constexpr int i = 0;
constexpr int const * ri = &i;

解决了这个问题。但是,如果变量是在函数作用域中定义的,这仍然是一个问题。

constexpr int i = 0;
constexpr int const* ri = &i;

int main() {}

是一个有效的程序。

void foo()
{
   constexpr int i = 0;
   constexpr int const* ri = &i;
}

int main() {}

不是有效的程序。

以下是 C++11 标准关于 地址常量表达式 的规定:

5.19 常量表达式

3.. 地址常量表达式是指针类型的纯右值核心常量表达式,其计算结果为具有静态存储持续时间的对象的地址、函数的地址或空指针值,或者类型的纯右值核心常量表达式

std::nullptr_t


8
投票

回复

如果我用 const 替换 constexpr 单词,以上所有操作都可以正常工作。”

A

const int*
本质上意味着
(const int)*
,只不过你不能那样使用括号。 A
constexpr int*
表示
constepxr (int*)
(同上)。

这是因为

constexpr
不是类型的一部分,你不能将类型命名为
constexpr int
,而
const
是类型的一部分。

而不是

constexpr int i = 0;
constexpr int& ri = i;

试图声明对非

constexpr
const
引用,只需写

constexpr int i = 0;
constexpr int const& ri = i;

您可以向后阅读,因为

ri
是对
const
int
的引用,即
constexpr
(在编译时评估)。


附录

似乎 C++14 要求本地非

static
constexpr
对象具有 自动存储持续时间,以 as-if 规则为模进行优化。

为了满足这一点,即使代码可以跨编译器移植,如果上述声明出现在函数本地,请添加

static
以确保引用的对象的静态存储持续时间:

void oops()
{
    static constexpr int i = 0;      // Necessary with some compilers.
    constexpr int const& ri = i;
}

否则它可能无法编译,例如g++,并且通过省略对 constexpr 的适当约束,这“可能”是 C++14 和 C++11 标准所要求的。


备注: 1 请参阅R. Sahu 的回答的讨论


5
投票
constexpr

是在

编译时
评估的。所以编译时该值必须是可评估的。 例如:

constexpr int i = 0; constexpr int& ri = i;

第一行,编译时可评估0,其值为0。

但是对于第二行,编译器需要

i

的地址来进行赋值,这是在运行时确定的。所以这条线会失败。

    


1
投票

constexpr

功能定义了编译期间发生的计算。合理的问题:


允许
    任何计算
  • 有意义吗?
  • 合理答案:

  • ,因为这需要编译器内部的大量机器、资源等,而没有直接需要。
  • 因为该标准允许在
constexpr

代码中使用相当有限的功能。有人可能会争论为什么是这个集合而不是其他东西?好吧,稍后标准可能会发展并允许更多。

    

© www.soinside.com 2019 - 2024. All rights reserved.