为啥编译器无法确定构造函数实际上是 constexpr?

Posted

技术标签:

【中文标题】为啥编译器无法确定构造函数实际上是 constexpr?【英文标题】:Why compiler cannot figure out that constructors are in fact constexpr?为什么编译器无法确定构造函数实际上是 constexpr? 【发布时间】:2017-08-08 21:00:15 【问题描述】:

考虑this code:

struct matrix

    matrix(int a, int b, int c, int d)
        : a(a), b(b), c(c), d(d)
    matrix()
        : a(0), b(0), c(0), d(0)
    int a, b, c, d;
;

static const matrix mx0;
static const matrix mx1(1,1,1,1);

const matrix& test(bool f)

    return f ? mx1 : mx0;

为什么编译器不能弄清楚并避免生成所有混乱的代码来初始化这两个全局静态 mx0mx1

为什么只有当我mark constructors constexpr 时,编译器才能在没有这个关键字的情况下做我期望它做的事情?请注意,启用优化的编译器 sill doesn't generate the same result 与 code that uses constexpr 一样。

【问题讨论】:

尝试优化。优化告诉编译器找出你没有告诉它的东西。 @KerrekSB 没错,我忘了添加-O2,不过,constexpr 产生的结果要好得多。 没有constexpr,初始化在运行时执行,而不是在编译时。在编译时初始化的东西更紧凑,因为编译器会计算出最终结果,然后只生成代码。 或switch to a better compiler? @Pavel:这种语言可以让你轻松地避免这些问题:constexpr 【参考方案1】:

首先让我说这是一个猜测,但(我相信)这是一个受过教育的猜测。

我不是 C++ 标准委员会的成员,但根据我在网上阅读和看到的内容,我可以告诉您,他们在向后兼容该语言的先前版本方面非常热心(现在仍然如此)。如果允许 C++11 编译器静默地将 constexpr 应用于构造函数并初始化 const 变量,那么这将改变在 C++11 下重新编译时现有程序的行为——从运行时初始化到编译时初始化.一般来说,在语言的更高版本中简单地重新编译时改变程序的行为被认为是一件坏事*。

因此,要获得以前无法实现的新行为,需要将原始代码更改为以前不合法的 C++ 代码。要求在构造函数(或其他函数)声明中使用新的 constexpr 关键字是一种简单有效的方法。


*当然,每个规则都有例外,例如编译器生成的移动构造函数/赋值运算符,但他们非常小心,除非可以证明是良性的,否则这些不能自动添加。

【讨论】:

我觉得是这个原因,但很好奇标准中是否存在阻止编译器应用这些优化的内容,或者这些优化是否会违反某些规则或要求 我的回答是指标准而不是编译器。基本上,编译器不会这样做,因为标准说不这样做;并且标准说不这样做,因为它有可能破坏现有代码。

以上是关于为啥编译器无法确定构造函数实际上是 constexpr?的主要内容,如果未能解决你的问题,请参考以下文章

为啥此 C++ 代码中的构造函数不明确,我该如何解决?

如果我尝试在不同的公共类中将数组作为参数传递,为啥我的构造函数无法在 Java 中编译?

为啥**不**将函数声明为`constexpr`?

C++:为啥我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段?

为啥当类包含任何参数化构造函数时编译器不提供默认构造函数? [复制]

默认构造函数,为啥我的类似乎有三个?当编译器将类视为结构时?