c++ - 为什么从 'const reference to base' 对象初始化 'constexpr derived' 对象不会产生常量表达式?

标签 c++ static constant-expression

我有这个简单的例子:

struct base
{
   constexpr base () {};
};
   
struct derived: public base
{
    constexpr derived () {};
};
  

int main() 
{
    constexpr derived d{};
    constexpr const base &b = d;  // why error?
}

G++ 给我以下错误:

error: '(const base&)(& d)' is not a constant expression

clang++ 给我以下错误:

error: constexpr variable 'b' must be initialized by a constant expression.

note: reference to subobject of 'd' is not a constant expression. Add 'static' to give it a constant address.

我很清楚 clang 给出了解决方案,但我不明白为什么问题解决了?

它说“对d的子对象的引用不是常量表达式。”,而这里的子对象有constexpr构造函数,为什么它不是常量表达式?

最后,我不明白为什么使用static可以解决问题?

请在答案中引用标准(如果可能)。

最佳答案

Clang给出的解释是正确的。

Constexpr 不会改变变量的存储(它在内存中的位置)。如果您声明一个非静态 constexpr 变量,它仍然会进入堆栈,就像所有其他非静态局部变量一样。

int test() {
  constexpr int a = 3; //a gets created here and put on the stack
  const int *b = &a; //Pointer to a location on the stack
} //a gets destroyed when the function ends

这意味着该局部变量的地址可以随着函数的每次调用而改变。在任何给定时间,变量也可以有多个拷贝,即如果多个线程执行函数或函数递归。

总的来说,局部变量的地址永远不能是常量表达式,无论该变量是 const、constexpr、volatile 还是其他任何类型。

static 关键字改变了这一点。它将局部变量“提升”到静态存储中,这意味着它的行为就像一个仅在该函数中可见的全局变量。特别是,变量有一个固定的地址,并且只有一个变量拷贝,无论函数执行的频率如何(如果有的话)。全局变量的地址是一个常量表达式。

如果您想要derived d 的单个全局常量实例,只需像 Clang 所建议的那样在其前面添加 static

关于c++ - 为什么从 'const reference to base' 对象初始化 'constexpr derived' 对象不会产生常量表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72119874/

相关文章:

java - 在 Java 17 switch-case 中使用 final 变量的好处

C 中初始化的结构成员不能用作整型常量吗?

c++ - 通过模板滥用的函数式 C++

c++ - 在 C++ 中为 STL 映射重载 [ ] 运算符

具有静态成员的 C++ 模板类 - 对所有类型的类都相同

python - 如何在 Python 中使用类变量作为默认参数值

java - Python 中的 PLSA 实现

c++ - 如何使用 ctypes 将数组从 C++ 函数返回到 Python

c - 静态是什么意思?

c++ - 如何使用 const 成员变量设置数组大小?