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/