c++ - 根据我的测试,[更有效的 C++] 中的第 3 项似乎无效

标签 c++ arrays polymorphism

Item3:Item 3:永远不要以多态方式对待数组

讲到在处理对象数组时,指针运算会根据指针的类型进行计算,不考虑多态/继承,所以结果会是一些随机值,但我针对VC/GCC做了测试

struct B{
    int i = 2;
    virtual ~B(){ cout << "B dtor\n"; }
};
struct D :B{
    int j = 3;
    int k = 4;
    int l = 5;
    ~D(){ cout << "D dtor\n"; }
};
void f(B* pb,size_t s)
{
    for (size_t i = 0; i < s; ++i)
        cout << pb->i << endl;
}
int main()
{
    B* pb = new D;
    delete pb;
    B* p2 = new D[2];
    f(p2,2);
    D buf[2];
    f(buf, 2);
    delete[] p2;
    return 0;
}

我预计,因为“虚拟”导致指向 vtable 的指针,sizeof(B) 应该是 8 而 sizeof(D) 应该是 16。所以在函数 f 中,访问 B[1].i 实际上是 D [0].k,所以我希望程序输出

2,4,2,4

但是VC编译运行这个程序,输出:

2,2,2,2

似乎 VC 有魔法让“f”知道它的输入数组是 de-factor“D”类型? 我也试过 GCC,它也打印“2,2,2,2”,但在“delete[] p2”时崩溃。

为什么这不是我的期望?为什么 GCC 的结果甚至会崩溃? 非常感谢。

最佳答案

你应该打印 cout << pb[i].i<< endl而不是 cout << pb->i << endl; .

#include <iostream>
using namespace std;
struct B {
    int i = 2;
    virtual ~B() { cout << "B dtor\n"; }
};
struct D : B {
    int j = 3;
    int k = 4;
    int l = 5;
    ~D() { cout << "D dtor\n"; }
};
void f(B* pb, size_t s)
{
    for (size_t i = 0; i < s; ++i)
        cout << pb[i].i<< endl;
}
int main()
{
    std :: cout << sizeof(B);
    std::cout << sizeof(D);
    B* pb = new D;
    delete pb;
    B* p2 = new D[2];
    f(p2, 2);
    D buf[2];
    f(buf, 2);
    delete[] p2;
    return 0;
}

这是为您提供所需行为的代码。作为备注 sizeof(B)确实是 8 但 sizeof(D)是 20,因为 D 包括 3 个整数(12 个字节),第 i 个来自基类的整数(4 个字节)和来自虚拟析构函数的指针(4 个字节)

关于c++ - 根据我的测试,[更有效的 C++] 中的第 3 项似乎无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38004705/

相关文章:

c++ - 汇编消息 : no such instruction when Compiling C++

arrays - perl6 在循环遍历数组时修改数组的一般方法

c# - 多态性、泛型和匿名类型 C#

haskell - 具有重载数字和字符串文字的类型类多态性

c++ - 如何使用参数中传递的初始值而不是更新后的值进行后续计算?

c++ - 即使我用 -L 指定了它的位置,链接器也找不到库

c++ - OpenGL - 重新绑定(bind)一个已经绑定(bind)的纹理

javascript - 通过几个分隔符将字符串拆分为数组

python - Numpy 列标题不是记录数组

haskell - polyTypeOf 很神秘