constexpr 函数是隐式静态的吗?

Are constexpr functions implicitly static?

如果我在 program.cpp 中定义一个函数:

constexpr bool isThree(const int number)
{
  return number == 3;
}

这与声明它为静态有什么不同吗?

static constexpr bool isThree(const int number)
{
  return number == 3;
}

看起来这些应该是等价的,因为 constexpr 意味着函数是内联的,因此不在编译单元之间共享。

constexpr 全局函数是隐式静态的吗?

constexpr 函数隐式 inline.

inline 是一个链接功能。在不同编译单元中定义的 inline 函数不是错误;如果它们的定义不同,则您的程序 ill-formed 不需要诊断,但如果它们具有相同的定义,则除一个版本外的所有版本都将被丢弃并使用该版本。

static,在 non-method 函数上,也是一个链接功能。 static 定义不在其编译单元之外共享;编译单元没有 'advertise' 它有 isThree.

的定义 方法函数上的

static 与链接无关。在那种情况下,它只是意味着 this 没有隐式传递给函数。一种方法 with/without this 它不起作用有差异,但它们大多与 constexpr 无关。请注意,至少 a constexpr method that doesn't use this can still be constant evaluated. Some versions of make constexpr methods implicitly const; 不会。

一个编译单元中的

&isThree 和另一个编译单元中的 &isThree 可以(并且通常会)在 static 时发生变化(除非激进的 ICF,这是另一个问题的问题)。当 inline 它们可能不会变化。

inline 函数 在编译单元之间共享。它们的完整定义也经常在所有知道它的编译单元中可见,因此它使编译器 "inlining"(与关键字相反)您的代码更容易。 static 不是。 constexpr 函数隐式 inline,但不是隐式 static

请注意,constexpr 函数有时可以在运行时上下文中求值。在编译时上下文中评估时,它们的 inlinestatic 或链接状态真的无关紧要。

constexpr 也有其他含义,但您想知道两个不同的 constexpr 声明之间的区别,并且 none 这些含义发生了变化。

constexpr 函数不是隐式静态的。它们与非 constexpr 函数具有相同的链接:

// external linkage
constexpr int f1(int x) { /* ... */ }

// internal linkage
static constexpr int f2(int x) { /* ... */ }

// internal linkage
namespace {
constexpr int f3(int x) { /* ... */ }
}

// no linkage
void enclosing() {
    struct S {
        constexpr int f4(int x) { /* ... */ }        
    };
}

当一个constexpr函数有外部链接时,它在所有翻译单元中有相同的地址。当它有内部链接时,每个翻译单元都有一个不同的副本,这些副本有不同的地址。但是,我相信 调用 一个 constexpr 函数的结果不应该取决于它是否具有内部或外部链接(因为 constexpr 函数可能不包含静态变量) .