首页 > 解决方案 > 在 C++ 中,如果一个成员引用在其声明中被初始化,为什么它需要存储空间?

问题描述

考虑这个例子。

struct S
{
    int j;
    inline static int i;
    int &ri{i};
};

S s;

static_assert(sizeof(s) > sizeof(int));

#include <type_traits>

static_assert(!std::is_standard_layout_v<S>);

https://godbolt.org/z/vWFkBC)。编译器为类内存布局中的引用保留空间。我想不出一个在其声明中初始化的成员引用显然有用的例子。也许这就是编译器不针对这种情况进行优化的原因。或者,标准中是否有禁止优化此参考的内容?

标签: c++

解决方案


在此类中,存储是必要的,以在运行时跟踪ri绑定到哪个对象,例如:

int main()
{
    int foo, bar;

    S s = { 3, rand() % 2 ? foo : bar };

    func(s);  // in other translation unit
}

但是,即使您提出程序可以在不需要存储的情况下运行的其他确切情况ri,这也意味着当程序经历一些细微的变化(或者您使用不同的-O优化标志)时,结构的大小会在不同的构建之间发生变化这使得优化不再可能。这通常不是程序员想要的行为,因此编译器不会这样做。

编译器还必须考虑 ABI 兼容性;用户认为头文件与由一个编译器构建的纯二进制库一起使用并使用不同的编译器合并到项目中是可取的。所以标题中指定的类应该有一个可预测的布局。

您可以提出类似的论点,即编译器可能不会分配存储,j只要它确定程序不使用j任何地方的值或地址,并且关于编译器为什么实际上不这样做的响应将是相似的。


推荐阅读