![](/img/trans.png)
[英]Is the constexpr specifier required on the declaration of a constexpr static member initialized outside of the class?
[英]C++ static constexpr member redeclaration outside of class
对于以下代码,为什么在不重新声明Foo :: bar的情况下main中的第一种情况可以正常工作,而使用该函数的第二种情况则需要它吗?
struct Foo{
static constexpr int bar = 30;
};
//Declaration of Foo::bar outside of struct
constexpr int Foo::bar;
int returnconstexpr(const int& x) { return x; }
int main()
{
//Ok without declaration outside of struct
std::cout << Foo::bar << std::endl;
//Requires declaration outside of struct
std::cout << returnconstexpr(Foo::bar) << std::endl;
//Here static constexpr works as a definition
static constexpr int x = 2;
std::cout << returnconstexpr(x) << std::endl;
return 0;
}
我认为这是因为在第一种情况下,编译器实际上只是停留在值中,而在第二种情况下,该函数需要的地址在没有重新声明的情况下尚不存在。 如果是这样,那么我要说的就是声明实际上是一个定义吗? 我对此感到困惑,因为在类中提供了初始化程序,但是它没有使它成为定义。 例如,第三种情况很好。
我认为这是因为在第一种情况下,编译器实际上只是停留在值中,而在第二种情况下,该函数需要的地址在没有重新声明的情况下尚不存在。 如果是这样,那么我要说的就是声明实际上是一个定义吗?
您已经回答了问题。 静态成员是在类外部定义的,因此您拥有的是定义。 当您将其传递给函数时,地址是必需的,因此您需要定义静态成员。 在第一种情况下,编译器只是将Foo::bar
替换为该值。
现在将函数签名更改为以下内容:
int returnconstexpr(int x) { return x; }
在上述情况下,您将不再需要定义。
此规则在C ++标准的3.2中:
除非使用x作为满足常量表达式(5.19)出现要求的对象并且ex是表达式e的潜在结果集合的元素,否则将使用其名称显示为可能值表达式ex的变量x。 ,其中将左值到右值转换(4.1)应用于e,或者e是舍弃值表达式(第5条)。
在上述情况下,将立即应用从左值到右值的转换,因此不会被过度使用(如标准所述),并且不需要定义。 简单来说,这意味着它可以只使用值,而无需知道地址,但是,当您使用引用类型(const int&)时,要求编译器知道对象在内存中的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.