【问题标题】:Are constexpr functions implicitly static?constexpr 函数是隐式静态的吗?
【发布时间】:2019-10-03 22:41:15
【问题描述】:

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

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

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

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

似乎它们应该是等价的,因为constexpr 表示该函数是内联的,因此不会在编译单元之间共享。

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

【问题讨论】:

  • 您的推理暗示staticinline 是相同的,但它们不是。实际上,这与 constexpr 的功能无关。
  • constexpr 是编译时特性,其中 inline/static 是运行时特性。
  • constexpr 的含义比 static 更受限制。意思是给定一个特定的输入值,返回值总是相同的,编译器应该能够在编译过程中完全解决它。静态函数仅在一个编译单元内具有作用域。返回的值可能会根据它访问的其他变量而改变。
  • @MichaelChourdakis inline 是一个运行时的东西吗?它主要是链接时间(ODR - 和可能的编译时间提示)。运行时代码已经生成,inline 早已不复存在/毫无意义。 static 也主要影响链接/可见性,而不是运行时行为。

标签: c++ c++11 constexpr static-functions


【解决方案1】:

constexpr 函数隐含为inline

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

static,在非方法函数上,也是一个链接特性。 static 定义不在其编译单元之外共享;编译单元不会“宣传”它具有isThree 的定义。

static 在方法函数上与链接无关。在这种情况下,它只是意味着 this 没有隐式传递给函数。带有/不带有this 的方法不起作用,但它们大多与constexpr 无关。请注意,至少在 中,不使用 thisconstexpr 方法仍然可以进行常量评估。某些版本的 使constexpr 方法隐含const 没有。

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

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

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

constexpr 也有其他含义,但您想知道两个不同的 constexpr 声明之间的区别,而这些含义都没有改变。

【讨论】:

  • static 在不同的上下文中表示不同的东西,但您只提到了一个含义。可以通过提及所有来改进答案。 ?
  • @JesperJuhl 当然,isThree 可能是在一个类中声明的,因此添加了一段关于此的内容。
【解决方案2】:

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 函数可能不包含静态变量)。

【讨论】:

    猜你喜欢
    • 2016-07-03
    • 2020-10-08
    • 1970-01-01
    • 2019-05-25
    • 2017-10-13
    • 2019-07-05
    • 1970-01-01
    • 2019-05-06
    • 2012-12-01
    相关资源
    最近更新 更多