【问题标题】:A question about sizeof and class member function关于sizeof和类成员函数的问题
【发布时间】:2010-10-08 08:40:37
【问题描述】:
 class B
{
   public:
     int a;
     void fn();
}

如果我创建一个 B 的对象,使用

B* pb = new B;

fn() 的内存定位在哪里?

对象中是否有指向 fn() 的内存位置的指针?

如果是,为什么 sizeof(B) 返回的值好像对象中根本没有指针一样?

【问题讨论】:

    标签: c++ sizeof


    【解决方案1】:

    fn() 的内存定位在哪里?

    因为它是一个普通函数,所以在程序代码部分的某个地方。对于类的所有实例,此位置相同。其实和B通过pb实例化无关。

    对象中是否有指向 fn() 的内存位置的指针?

    没有。对于普通的成员函数,这不是必需的,因为地址在编译时(或者最迟在链接时)是已知的;因此它不必在运行时单独存储。

    对于虚函数,情况就不同了。虚函数指针存储在一个数组中(称为“虚函数指针表”或简称“vtable”)。每个类都有一个这样的 vtable,并且每个类的实例都存储一个指向该 vtable 的指针。这是必要的,因为如果Base 类型的指针/引用指向子类Derived,编译器无法知道要调用哪个函数;相反,正确的函数是在运行时通过在关联的 vtable 中查找来计算的。 vtable 指针在sizeof 对象中也很明显。

    【讨论】:

    • 如果 fn() 是虚拟的,那么某处的内存部分(称为 vtable)将包含指向 B::fn() 的指针。该类只有一个,而不是每个类对象一个,因此不会显示在 sizeof(B) 中。
    • 大卫:好吧。每个类只有一个 vtable,是的。但是,每个实例都有一个指向该 vtable 的指针,并且指针大小确实确实显示在 sizeof(B) 中。我会澄清这一点。
    【解决方案2】:

    这个:

    class B
    {
       public:
         int a;
         void fn();
    };
    

    在所有实际目的上都等同于 C 代码:

    struct B
    {
       int a;
    };
    
    void fn(B* bInstance);
    

    除了在 C++ 版本中 bInstance 被替换为 this 指针。这两个函数的内存都存在于堆栈中。那么转换为 struct equivelant,你认为 sizeof(B) 会是什么?

    【讨论】:

    • 使函数参数const 更准确——也许把它放在一个自己的命名空间中。不过,这可能会分散您的注意力。 ;-)
    • 参数不是const,因为它没有声明为void fn() const;
    【解决方案3】:

    只会为虚拟函数(在 vtable 中)存储一个指针,而不是为非虚拟函数存储一个指针。

    【讨论】:

      【解决方案4】:

      1) B* pb = new B 将在堆上分配内存。这意味着,除其他外,您需要通过 delete 运算符自行清理它。或者,您可以将指针放在智能指针(shared_ptr、auto_ptr.scope_ptr)中并让它进行清理。

      2) 因为指针是类型,指向一个对象或者null,有定义的大小,通常等于int。

      3) fn() 不是虚函数,因此对象中没有为 vtable 分配内存。

      【讨论】:

        猜你喜欢
        • 2020-01-30
        • 2013-04-10
        • 2020-12-02
        • 1970-01-01
        • 2020-04-02
        • 1970-01-01
        • 2021-06-23
        • 1970-01-01
        相关资源
        最近更新 更多