请考虑以下设置.
class I
{
public:
virtual void F() = 0;
};
class A : public I
{
public:
void F() { /* some implementation */ }
};
class B : public I
{
public:
void F() { /* some implementation */ }
};
Run Code Online (Sandbox Code Playgroud)
这允许我编写如下函数.
std::shared_ptr<I> make_I(bool x)
{
if (x) return std::make_shared<A>();
else return std::make_shared<B>();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我为继承和多态性支付一些费用,即有一个vtable,并且F
当使用时调用不能内联如下(如果我错了,请纠正我).
auto i = make_I(false);
i->F(); //can't be inlined
Run Code Online (Sandbox Code Playgroud)
我想知道的是,当使用A
或B
作为堆栈上分配的对象时,我必须支付相同的费用,如下面的代码所示.
A a;
a.F();
Run Code Online (Sandbox Code Playgroud)
做A
和B
在栈上分配有虚函数表?电话会F
被内联吗?
这似乎对我来说,编译器可以可行建立在继承层次的类两个内存布局-一个栈和一个用于堆.这是C++编译器将要/可能做的事情吗?或者是否存在理论或实践原因?
编辑:
我看到一条评论(看起来像是被删除了)实际上提出了一个好点.你总是可以做以下事情,然后A a
在堆栈上分配可能不是我想要的重点......
A a;
A* p = &a;
p->F(); //likely won't be inlined (correct me if I'm wrong)
Run Code Online (Sandbox Code Playgroud)
也许用它来表达它的更好方法是"对于在堆栈上分配的对象的行为是否不同而被用作'常规值类型'?" 如果你知道我的意思,请用这个术语帮助我,但是有更好的方法!
我试图了解的一点是,在编译时,您可以将基类的定义"压扁"到您在堆栈上分配实例的派生类.
我认为你的问题实际上与编译器是否具有对象的静态知识有关,并且可以忽略vtable查找(你在编辑中提到过这一点),而不是对象存在的位置 - 堆栈或堆.是的,在这种情况下,许多编译器可以忽略虚拟调度.
归档时间: |
|
查看次数: |
270 次 |
最近记录: |