关于 sizeof winrt Demo 对象
about the sizeof winrt Demo object
我很好奇一个非常简单的 Demo 对象的大小,所以,我正在编写以下代码
</p>
#include <windows.h>
#include "winrt/base.h"
#include <iostream>
#pragma comment(lib, "windowsapp")
/*
cl /nologo /await /std:c++latest /wd4002 /EHsc base_so.cpp
*/
using namespace std;
using namespace winrt;
using namespace winrt::impl;
struct IDemo;
template <typename D>
struct consume_IDemo
{
void hello();
};
template <> struct consume<IDemo> { template <typename D> using type = consume_IDemo<D>; };
template <typename D> void consume_IDemo<D>::hello()
{
WINRT_SHIM(D)->hello();
}
struct WINRT_EBO __declspec(uuid("3A44B7CC-9CB6-4512-8CAD-6400E662D865"))
IDemo : Windows::Foundation::IInspectable, consume_t<IDemo>
{
IDemo(std::nullptr_t = nullptr) noexcept {};
};
template <> struct abi<IDemo>
{
struct type : IInspectable
{
virtual HRESULT hello() = 0;
};
};
template <typename D>
struct produce<D,IDemo> : produce_base<D,IDemo>
{
HRESULT hello() override
{
shim().hello();
return S_OK;
}
};
struct Demo : implements<Demo,IDemo>
{
Demo()
{
cout << "sizeof Demo 0x" << hex << sizeof(*this) << dec << endl;
cout << "sizeof m_references 0x" << hex << sizeof(std::atomic<std::conditional_t<1, uintptr_t, uint32_t>>) << dec << endl;
cout << "is_composing " << is_composing << endl;
cout << "outer " << outer() << endl;
}
HRESULT hello()
{
cout << __FUNCTION__ << endl;
return S_OK;
}
};
int main()
{
Demo d;
}
输出为
sizeof 演示 0x18
sizeof m_references 0x8
is_composing 0
外部 0000000000000000
我认为 Demo 的 sizeof 应该是 0x10 (64 机器) : sizeof(m_references)+sizeof(produce) 那么,额外的 8 个字节是多少?非常感谢!
要么是padding,要么是v-tables。也许两者都...
编译器可能会为每个至少声明了一个虚方法的基 class 插入一个 v-table 指针。 (顺便说一句,当你从具体的 class 到非第一个基础 class 进行 C 转换时,static_cast 或 dynamic_cast,编译器将改变指向 base-class 或其 v-table 的指针值。)
让我们分解一下。
Demo
继承自 implements<Demo,IDemo>
implements
定义如下:
struct implements : impl::producers<D, I...>, impl::base_implements<D, I...>::type
{
现在我们进入 WinRT 噪音。但它似乎确实暗示了多重继承。但是用调试器来解决这个问题更容易……你去吧。第一个 vtable 用于 IUnknown。另一个是IInspectable.
相关的东西
所以这是有道理的。每个 v-table 都是一个 8 字节的指针。而 m_references 也是 8 个字节。 8+8+8 = 24 = 0x18
我很好奇一个非常简单的 Demo 对象的大小,所以,我正在编写以下代码
</p>
#include <windows.h>
#include "winrt/base.h"
#include <iostream>
#pragma comment(lib, "windowsapp")
/*
cl /nologo /await /std:c++latest /wd4002 /EHsc base_so.cpp
*/
using namespace std;
using namespace winrt;
using namespace winrt::impl;
struct IDemo;
template <typename D>
struct consume_IDemo
{
void hello();
};
template <> struct consume<IDemo> { template <typename D> using type = consume_IDemo<D>; };
template <typename D> void consume_IDemo<D>::hello()
{
WINRT_SHIM(D)->hello();
}
struct WINRT_EBO __declspec(uuid("3A44B7CC-9CB6-4512-8CAD-6400E662D865"))
IDemo : Windows::Foundation::IInspectable, consume_t<IDemo>
{
IDemo(std::nullptr_t = nullptr) noexcept {};
};
template <> struct abi<IDemo>
{
struct type : IInspectable
{
virtual HRESULT hello() = 0;
};
};
template <typename D>
struct produce<D,IDemo> : produce_base<D,IDemo>
{
HRESULT hello() override
{
shim().hello();
return S_OK;
}
};
struct Demo : implements<Demo,IDemo>
{
Demo()
{
cout << "sizeof Demo 0x" << hex << sizeof(*this) << dec << endl;
cout << "sizeof m_references 0x" << hex << sizeof(std::atomic<std::conditional_t<1, uintptr_t, uint32_t>>) << dec << endl;
cout << "is_composing " << is_composing << endl;
cout << "outer " << outer() << endl;
}
HRESULT hello()
{
cout << __FUNCTION__ << endl;
return S_OK;
}
};
int main()
{
Demo d;
}
输出为
sizeof 演示 0x18
sizeof m_references 0x8
is_composing 0
外部 0000000000000000
我认为 Demo 的 sizeof 应该是 0x10 (64 机器) : sizeof(m_references)+sizeof(produce
要么是padding,要么是v-tables。也许两者都...
编译器可能会为每个至少声明了一个虚方法的基 class 插入一个 v-table 指针。 (顺便说一句,当你从具体的 class 到非第一个基础 class 进行 C 转换时,static_cast 或 dynamic_cast,编译器将改变指向 base-class 或其 v-table 的指针值。)
让我们分解一下。
Demo
继承自 implements<Demo,IDemo>
implements
定义如下:
struct implements : impl::producers<D, I...>, impl::base_implements<D, I...>::type
{
现在我们进入 WinRT 噪音。但它似乎确实暗示了多重继承。但是用调试器来解决这个问题更容易……你去吧。第一个 vtable 用于 IUnknown。另一个是IInspectable.
相关的东西所以这是有道理的。每个 v-table 都是一个 8 字节的指针。而 m_references 也是 8 个字节。 8+8+8 = 24 = 0x18