Class 在 C++ 中的 Class 内部:它很重吗?

Class Inside a Class in C++: Is that heavy?

假设我做了类似的事情:

class A
{
public:
    class B
    {
    public:
         void SomeFunction1() const;
         using atype = A;
    };

    using btype = B;
    void SomeFunction2() const;

private:
    B b;
};

然后我创建一个 class A 的实例并复制它:

A a;
A acopy = a;

这是否使 class 变得沉重,我的意思是,后台发生了什么?我希望每次声明 class A 的实例时,C++ 都不会真的从字面上“考虑” class B 的定义,我想在后台发生的事情是 class B将被视为名为 A 的名称空间下的新定义,因此定义了 A::B。我的问题是在 class 中定义 class(A 中的 B)是否会在声明或复制 class A 时产生任何开销,或者它是否被完全视为 B 是在外部定义的?

谢谢大家:)

我个人的看法是:

  • 即使源代码折叠,阅读起来也很沉重。
  • 它通常没用:B class 大多数时候可以与 A class 完全合并。
  • 即使 B 如果 A 需要,并且 从来没有 在其他地方使用过,它可以在 A 之外定义。构造函数是您“强制”某些关联的朋友 - 例如,删除默认构造函数。
  • 在内部或外部 A,它不会改变任何有关深层复制的内容。
  • 如果您需要直接通过 A 公开 B,这是一个设计缺陷 - 将这些功能从 B 移至 A

所以我真的看不出,除了“保留”头文件之外,通过在 class...

中声明 class 可以“获得”什么

就我而言,我更喜欢:

  • 如果不需要公开,请使用 PIMPL idiom“隐藏”B
  • 永久移动需要在 A 中公开的所有内容(移动源代码),或者对 PIMPL 对象使用包装器。
  • 如果您需要 replace/share B 实例,请将 PIMPL 对象的 unique_ptr 更改为 shared_ptr。注意深拷贝。

它通常效率更高,如果需要,可以完美隐藏 B 代码(例如,甚至不需要从 DLL 导出它),您不会重新编译 B所有这些都是在更改 A 时进行的,您甚至可以在不破坏 A API.

的情况下更改 B 的工作方式

C++ 是一种编译语言。我们通常假设用于编译 C++ 源代码的计算机足够强大。编译器在编译可执行文件的过程中可以合理地使用千兆字节。

所以当我们说某些东西“很重”时,我们通常是指它在运行时很重。 C++ 程序的运行时环境很可能是咖啡机或冰箱。

嵌套范围内的名称查找之类的事情是纯粹的 compile-time 操作,不会对运行时产生任何影响。现代编译器足够聪明,可以在此处内联默认方法,因此调用成员时没有运行时开销。

两种可能性(B 作为嵌套 class 和 B 作为外部 class)将产生完全相同的性能。

事实上,编译器在两种情况下都会生成相同的汇编代码。

B 作为外部 class:

https://godbolt.org/z/7voYGd6Mf

B 嵌套 class:

https://godbolt.org/z/731dPdrqo

B 是 A 的成员。因此它驻留在 A 的内存布局中,每次 constructor/copy A 时都会调用 B 的构造函数。 引入的开销取决于 B 实现,但在两种情况下都是相同的(B 嵌套和外部 class),

所以我是问这个问题的人,我已经测试了@david dragilev 在 Google Benchmark 上实现的内容。结果附上,确实差别很小。我不能说外部版本更快,但理论上(基于数字)是。

结果:https://quick-bench.com/q/sgwCs8kHfePvAaFeLe03uqmCsIo