- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在阅读 here关于如何选择主要碱基:
"...2. If C is a dynamic class type:
a. Identify all virtual base classes, direct or indirect, that are primary base classes for some other direct or indirect base class. Call these indirect primary base classes.
b. If C has a dynamic base class, attempt to choose a primary base class B. It is the first (in direct base class order) non-virtual dynamic base class, if one exists. Otherwise, it is a nearly empty virtual base class, the first one in (preorder) inheritance graph order which is not an indirect primary base class if any exist, or just the first one if they are all indirect primaries..."
在更正之后:
"Case (2b) above is now considered to be an error in the design. The use of the first indirect primary base class as the derived class' primary base does not save any space in the object, and will cause some duplication of virtual function pointers in the additional copy of the base classes virtual table.
The benefit is that using the derived class virtual pointer as the base class virtual pointer will often save a load, and no adjustment to the this pointer will be required for calls to its virtual functions.
It was thought that 2b would allow the compiler to avoid adjusting this in some cases, but this was incorrect, as the virtual function call algorithm requires that the function be looked up through a pointer to a class that defines the function, not one that just inherits it. Removing that requirement would not be a good idea, as there would then no longer be a way to emit all thunks with the functions they jump to. For instance, consider this example:
struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};
When B and C are declared, A is a primary base in each case, so although vcall offsets are allocated in the A-in-B and A-in-C vtables, no this adjustment is required and no thunk is generated. However, inside D objects, A is no longer a primary base of C, so if we allowed calls to C::f() to use the copy of A's vtable in the C subobject, we would need to adjust this from C* to B::A*, which would require a third-party thunk. Since we require that a call to C::f() first convert to A*, C-in-D's copy of A's vtable is never referenced, so this is not necessary."
能否请您举例说明这指的是什么:“删除该要求不是一个好主意,因为那样就不再有办法用它们跳转到的函数发出所有 thunk ”?
此外,什么是第三方 thunk?
我也不明白引用的示例试图显示什么。
最佳答案
A
是一个几乎是空的类,它只包含一个 vptr 而没有可见的数据成员:
struct A { virtual void f(); };
A
的布局是:
A_vtable *vptr
B
有一个几乎是空的基类用作“主要”:
struct B : virtual public A { int i; };
这意味着 B
的布局从 A
的布局开始,因此指向 B
的指针是指向A
(汇编语言)。 B
子对象的布局:
B_vtable *A_vptr
int i
A_vptr
显然会指向一个B
vtable,它与A
vtable 二进制兼容。
B_vtable
扩展了 A_vtable
,添加了所有必要的信息以导航到虚拟基类 A
。
B
完整对象的布局:
A base_subobject
int i
同样适用于 C
:
C_vtable *A_vptr
int j
C
完整对象的布局:
A base_subobject
int j
在D
中显然只有一个A
子对象,所以一个完整对象的布局是:
A base_subobject
int i
not(A) not(base_subobject) aka (C::A)_vptr
int j
not(A)
是一个A
几乎为空的基类的表示,即A
的vptr,但不是a true A
子对象:它看起来像一个A
但可见的A
是上面的两个词。这是一个幽灵 A
!
(C::A)_vptr
是指向具有 C
布局 vtable 的 vtable 的 vptr(因此也是具有 A
布局 vtable 的 vptr ),但对于 A
最终不是主要基础的 C
子对象:C
子对象已失去托管 的特权一个
基类。所以很明显,通过 (C::A)_vptr
对虚函数定义的虚函数调用 A
(只有一个:A::f()
) 需要一个 this
调整,带有一个接收指向 not(base_subobject)
的指针的“C::A::f()
” > 并将其调整为 A
类型的真实 base_subobject
,即(示例中上面的两个词)。 (或者,如果 D
中有覆盖程序,则 D
对象位于完全相同的地址,示例中上面的两个词。)
所以给定这些定义:
struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};
应该使用不存在的 A
主基的幽灵左值吗?
D d;
C *volatile cp = &d;
A *volatile ghost_ap = reinterpret_cast<A*> (cp);
ghost_ap->f(); // use the vptr of C::A: safe?
(此处使用volatile
以避免编译器传播类型知识)
如果对于 C
的左值,对于从 A
继承的虚函数,调用是通过 C
vptr 完成的也是一个 C::A
vptr,因为 A
是 C
的“静态”主基,那么代码应该可以工作,因为一个 thunk已生成从 C
到 D
。
在实践中它似乎不适用于 GCC,但是如果您在 C
中添加覆盖程序:
struct C : virtual public A {
int j;
virtual void f()
{
std::cout << "C:f() \n";
}
};
之所以有效,是因为这样的具体函数在 C::A
的 vtable 的 vtable 中。
即使只有一个纯虚拟覆盖:
struct C : virtual public A {
int j;
virtual void f() = 0;
};
和 D
中的具体覆盖,它也可以工作:纯虚拟覆盖足以在 C::A
的 vtable 中拥有正确的条目。
关于c++ - Itanium C++ ABI 主要虚拟基础,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44433386/
有人告诉我: [ABIs] guarantee the exact layout of the struct, byte offset of every member, which bits are
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
我正在阅读 here关于如何选择主要碱基: "...2. If C is a dynamic class type: a. Identify all virtual base classes, dir
寻找可用于检测 HP-UX Itanium 平台上的静态/运行时内存泄漏的各种工具(免费/商业)。 背景,我们: 使用 HP-UX 11.31 ia64。但是,我们所有的应用程序仍然只有 32 位。
Itanium ABI 指出异常的内存是通过调用 __cxa_allocate_exception(size) 获得的。返回内存的对齐保证是什么? 最佳答案 Section 1.2 in chapte
我正在开发 C/C++ 跨平台代码,最后一个平台是基于 Itanium 的 HP-UX。问题末尾可以找到相关的机器和处理器信息。 我需要为下面给出的机器和编译器规范实现或找到原子比较和交换。 我已经找
我正在尝试调试使用 libevent 库的代码。在该库中,有一个函数 event_new 假设创建一个 event_cb。不知何故,在我分派(dispatch)事件库后,无法调用或访问 event_c
我需要在 HPUX(Itanium 和 PARISC)中获取用于交换信息的命令。 最佳答案 这是 unix.stackexchange 的链接那对我有帮助。谢谢@乔纳森 /usr/sbin/swapi
我正在阅读 Itanium ABI上面写着 It is intended that two type_info pointers point to equivalent type descriptio
我需要为 Itanium 编译我的代码,但似乎所有编译器(ecc、gcc、orc)都需要 Itanium 机器来执行此操作。有什么建议吗? 最佳答案 您需要将 gcc 设置为交叉编译器。这涉及到自己构
例如: template struct foo { using bar = int; }; // _Z3bazi void baz(foo::bar quux) { } template
昨天我了解到,针对 AMD64 和 Itanium 目标进行编译时,Microsoft Visual C++ 不支持内联汇编(使用 __asm 关键字)。 这是正确的吗?如果是这样,有谁知道为什么他们
我在同时运行 64 位 Oracle 10.2 的 64 位 Itanium 服务器上运行 Windows Server 2003,我想为 Python 2.5 安装 cx_Oracle。我之前在 W
我是一名优秀的程序员,十分优秀!