C ++静态constexpr成员在课堂外重新声明

时间:2014-02-25 22:02:38

标签: c++ struct static definition constexpr

对于下面的代码,为什么主要工作中的第一个案例没有重新声明Foo :: bar,而第二个案例需要它?

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;
}

我假设这是因为在第一种情况下,编译器实际上只是粘在该值中,而在第二种情况下,该函数需要一个在没有重新声明的情况下尚不存在的地址。如果是这样,那么我所说的是宣言实际上是一个定义吗?我对此感到困惑,因为类中提供了初始化器,但它没有使它成为定义。例如,第三种情况就可以了。

1 个答案:

答案 0 :(得分:1)

  

我假设这是因为在第一种情况下,编译器   字面上只是坚持价值,而在第二种情况下   函数需要一个没有的地址   重声明。如果是这样,那么我所说的就是   声明实际上是一个定义?

你已经回答了这个问题。静态成员在类之外定义,所以你拥有的是一个定义。将其传递给函数时,地址是必需的,因此您需要定义静态成员。在第一种情况下,编译器只需将Foo::bar替换为值。

现在将函数签名更改为以下内容:

int returnconstexpr(int x) { return x; }

在上述情况下,您将不再需要该定义。

这个规则是在C ++标准的3.2中:

  

变量x,其名称显示为可能已评估的表达式   ex是odr-used,除非x是满足要求的对象   出现在常量表达式(5.19)中,ex是一个元素   表达式e的潜在结果集,其中任何一个   左值到左值的转换(4.1)适用于e,或e是a   丢弃值表达式(第5条)。

在上述情况下,立即应用左值到右值的转换,因此它没有使用(如标准所述)并且不需要定义。简单来说,这意味着它可以只使用该值而不需要知道地址,但是当您使用引用类型(const int&amp;)时,需要编译器知道对象在内存中的位置。