【问题标题】:constexpr const char* in header file头文件中的 constexpr const char*
【发布时间】:2019-07-20 08:28:33
【问题描述】:

是否有理由不在头文件中使用“constexpr const char*”?

一位同事的论点是,包括这个头文件的每个翻译单元都会有一个副本。

我的理解是,由于它的编译时常量,没有分配内存,并且在内存使用方面更像是“#define”宏。 这是来源,

TestConstExpr.h

  #include <string.h>
  namespace TestConstExpr
  {
    constexpr const char* TIME_FORMAT = "yyyy-MM-dd hh:mm:ss";
    constexpr const int TIME_FORMAT_SIZE = strlen(TIME_FORMAT) + 1;

    class TestClass
    {
        char arr[TIME_FORMAT_SIZE];
    }
  }

【问题讨论】:

  • char const *?当然不是,对常量数组或 getter 函数的引用 - 要走的路。另外你的理解也不对。内存的分配方式与在源文件中的分配方式完全相同。
  • 我建议你用 bloaty mcbloatface 试试 - 将这些头文件编译成多个 TU,然后用 -O2 将它们链接在一起,看看字符串是否重复!

标签: c++ c++11


【解决方案1】:

一位同事的论点是,包括这个头文件的每个翻译单元都会有一个副本。

您的同事在技术上是正确的。但这没关系,因为当单元链接在一起时,多余的副本会被丢弃。

虽然,我已经看到 cmets 在涉及动态链接时,在某些不符合标准的系统上不一定会出现这种情况。


constexpr const char* TIME_FORMAT = "yyyy-MM-dd hh:mm:ss";
.... sizeof(TIME_FORMAT)

这并不像您认为的那样。它为您提供指针的大小,而不是指向字符串的大小。

constexpr const int TIME_FORMAT_SIZE = strlen(TIME_FORMAT) + 1;

您尝试的修复也不起作用,因为strlen 不是常量表达式。

您可以通过使用对字符串文字的引用来解决问题:

static constexpr auto& TIME_FORMAT = "yyyy-MM-dd hh:mm:ss";
constexpr const int TIME_FORMAT_SIZE = sizeof(TIME_FORMAT);

【讨论】:

  • 如果该标头包含在多个 cpp 文件中,则使用字符串文字会引发多个定义错误。 `TestConstExpr::TIME_FORMAT'的多重定义
  • @NaveenGara 似乎由于某种原因该变量默认具有外部链接,尽管它是 constexpr。您可以使用static 关键字显式使用内部链接。
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 2016-07-24
相关资源
最近更新 更多