纯虚拟类上的 DECLSPEC_NOVTABLE?
这可能是习惯性的编程冗余。 我注意到标题中定义的一堆接口上有 DECLSPEC_NOVTABLE ( __declspec(novtable) ):
struct DECLSPEC_NOVTABLE IStuff : public IObject
{
virtual method1 () = 0;
virtual method2 () = 0;
};
MS 文档 表示,添加这个家伙将删除构造函数和析构函数 vtable 条目,从而导致“代码大小显着减少”(因为 vtable 将被完全删除)。
这对我来说没有多大意义。 这些家伙是纯虚拟的,为什么编译器不默认这样做呢?
该文章还指出,如果您这样做,然后尝试实例化其中一项,您将遇到运行时访问冲突。 但是当我用一些编译器(带或不带 __declspec 扩展)尝试这个时,它们不会编译(正如我所期望的)。
所以我想总结一下:
- 编译器是否会删除 vtable,无论纯虚拟接口如何,还是我在这里错过了一些基本的东西?
- MSDN 文章谈论的是什么?
This is probably habitual programming redundancy. I have noticed DECLSPEC_NOVTABLE ( __declspec(novtable) ) on a bunch of interfaces defined in headers:
struct DECLSPEC_NOVTABLE IStuff : public IObject
{
virtual method1 () = 0;
virtual method2 () = 0;
};
The MS docs on this __declspec extended attribute says that adding this guy will remove the construct and desctructor vtable entries and thus result in "significant code size reduction" (because the vtable will be removed entirely).
This just doesn't make much sense to me. These guys are pure virtual, why wouldn't the compiler just do this by default?
The article also says that if you do this, and then try and instantiate one of these things, you will get a run time access violation. But when I tried this with a few compilers (with or without the __declspec extension), they don't compile (as I would have expected).
So I guess to summarize:
- Does the compiler strip out the vtable regardless for pure virtual interfaces, or have I missed something fundamental here?
- What is the MSDN article talking about ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编译器会删除对 vtable 的唯一引用,这本来是在类的构造过程中进行的。 因此,链接器可以优化它,因为代码中不再引用它。
顺便说一句,我养成了将空构造函数声明为受保护的构造函数的习惯,并且还使用 Microsoft 的扩展抽象关键字,以避免运行时的访问冲突。 这样,编译器可以在编译时捕获问题(因为只有基类可以通过受保护的构造函数实例化接口)。 派生类当然会在构造期间填充 vtable。
The compiler strips out the only reference to the vtable, which would have been during construction of the class. Therefore, the linker can optimize it away since there is no longer a reference in the code to it.
Also by the way, I have made a habit of declaring an empty constructor as
protected
, and also using Microsoft's extensionabstract
keyword, to avoid that access violation at runtime. This way, the compiler catches the problem at compile time instead (since only a base class can instantiate the interface through the protected constructor). The derived class will of course fill in the vtable during its construction.对于一个愚蠢的编译器/链接器来说,这是一种掌握。 编译器不应插入对此 vtable 的任何引用,因为很明显不需要此 vtable。 编译器还可以以链接器可以消除 vtable 的方式标记引用,但这当然更复杂。
It's a bit of handholding for a dumb compiler/linker. The compiler should not insert any reference to this vtable, as it is quite obvious that there is no need for this vtable. The compiler could also mark the reference in such a way that the linker can eliminate the vtable, but that's more complex of course.