【问题标题】:Can multiple 'const reference' variables share the same memory?多个“常量引用”变量可以共享相同的内存吗?
【发布时间】:2020-07-03 10:48:55
【问题描述】:

我想知道在同一范围内有多个“常量引用”变量指向同一个对象是否会产生内存成本:

const Animal& animal = getAnimal();
const Dog& dog = static_cast<const Dog&>(animal);

从概念上讲,animaldog 是两个变量,每个都是指针大小,因此会占用 2 个寄存器(或堆栈上的 2*指针大小区域)。

但是(假设没有多重继承等),编译器可以知道它们在整个生命周期中都必须保持相同的指针值。

那么,这两个变量可以共享一个寄存器(或堆栈上的一个指针大小的区域)吗?
我所说的“可以”是指:

  • C++ 标准是否允许这样做?
  • 现代编译器会这样做吗?

【问题讨论】:

  • "是两个变量,每个指针的大小"你怎么知道?我不知道有什么方法可以获取参考本身的大小
  • C++ 有“好像”规则。在某些限制条件下,只要程序的可观察行为没有改变,编译器就可以随心所欲地做任何事情。因此,C++ 标准当然允许编译器为两个引用共享一个位置(甚至完全消除两个引用)。编译器在实践中是否真的会这样做可能取决于许多不同的因素。

标签: c++ memory reference compiler-optimization


【解决方案1】:

C++ 标准允许吗?

当然,为什么不呢。您无法分辨出其中的区别。所谓的“as-if rule”允许编译器进行任何优化,只要可观察的行为与没有进行任何优化一样(旁注:有例外,允许优化改变可观察的行为) .

从概念上讲,animal 和 dog 是两个变量,每个变量的指针大小,...

不。从概念上讲,引用是别名。它们不需要占用任何空间,因为它们只是实际对象的不同名称。 C++ 标准没有指定引用的大小或实现方式。 sizeof 引用为您提供所引用对象的大小。引用的地址是被引用对象的地址。如果引用是作为指针实现还是以任何其他方式实现,我不知道有什么方法可以区分(我强烈怀疑是否存在可移植方式)。

现代编译器会这样做吗?

要回答这个问题,我建议您使用一些真实的代码并查看编译器的输出。这是一个很好的工具来帮助解决这个问题:https://godbolt.org/

PS:我感觉有点小误会。实际上,您示例中的 const 并不相关。拥有const 引用并不意味着该值不会改变。这仅意味着您不允许通过该引用更改值。也许最好用一个小例子来解释:

struct foo {
    const int& ref;
};

int main() {
    int x = 1;
    foo f{x};
    x = 42;
}    

这里f 持有constx 的引用。这并不意味着x 永远不会被修改。这只意味着f不能通过ref修改x。这在多线程环境中尤其重要,在多线程环境中,假设一个对象是 const 只是因为你有一个 const 引用会导致麻烦。

【讨论】:

  • 除了不能做的事情外,引用在概念上等同于指针真的不正确吗? (例如,您无法测量引用的地址或大小)
  • 实际上您可以测量参考的大小:在上一个示例中为sizeof(struct foo)
  • @user253751 “概念上”可以使用类比,但我从来没有看到说引用就像指针有什么好处,而是很多误解都基于此
  • @user253751 你如何区分填充和成员的大小?类型的大小不是其成员大小的总和。此外,无论您测量什么,下次可能会有所不同
  • 你对std::has_unique_object_representations_v&lt;foo&gt;有什么看法?
【解决方案2】:

多个“常量引用”变量可以共享相同的内存吗?

当然,变量有时可以共享内存。在某些情况下,两个变量都不会使用任何内存。

这适用于所有平凡的类型。

从概念上讲,animal和dog是两个变量,每个变量都是指针大小

在概念上,该标准没有指定参考的大小。但实际上,如果引用变量需要存储,那么它确实是指针的大小。

C++ 标准允许吗?

是的。

现代编译器会这样做吗?

取决于上下文。在某些情况下他们会,而在实际上却做不到的情况下。

【讨论】:

    猜你喜欢
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多