在C ++中,当调用函数时,会向调用堆栈添加一个新的堆栈帧,其中包含其参数和局部变量(以及其他内容)。调用对象构造函数时是否也会发生这种情况? 如果是这样,当构造函数使用初始化列表时,这会改变吗?这个堆栈框架的结构是什么?它是否包含对象的成员变量(在执行构造函数后必须在堆中)?
答案 0 :(得分:2)
您不需要特别考虑构造函数。它只是一种功能 - 例如,这个C ++代码是
class Test
{
private:
int m_a;
public:
Test() : m_a(0) { puts("Test::Test()"); }
explicit Test(int i) : m_a(i) { puts("Test::Test(int)"); }
void f(char c) { puts("Test::f(char)"); }
~Test() { puts("Test::~Test()");
};
int main()
{
Test t1;
Test t2(3);
t1.f('a');
}
几乎与
类似struct Test
{
int m_a;
};
void Test__ctor_0(Test *thiz) { thiz->m_a = 0; puts("Test::Test()"); }
void Test__ctor_1(Test *thiz, int i) { thiz->m_a = i; puts("Test::Test(int)"); }
void Test__f(Test *thiz, char c) { puts("Test::f(char)"); }
void Test__dtor_(Test *thiz) { puts("Test::~Test()"); }
int main()
{
struct Test t1;
Test__ctor_0(&t1);
struct Test t2;
Test__ctor_1(&t2, 3);
Test__f(&t1, 'a');
Test__dtor_(&t1);
Test__dtor_(&t2);
}
这个C代码。
当然,可以在调用ctor时创建堆栈帧,如果它没有内联,或者编译器优化调用而不是创建堆栈帧以减少性能下降。
(在x86的cdecl中,this
指针通过ecx
寄存器发送,与其他参数不同。所以如果构造函数不使用任何局部变量且没有任何其他参数,则堆栈框架可能无法创建。)
答案 1 :(得分:1)
构造与任何其他方法调用一样处理。
如果它没有被优化器内联,那么将创建一个堆栈帧,其中包含一个隐含的"这个"指针和所有传入的参数。
答案 2 :(得分:0)
大多数架构' ABI通过将this
- 指针放入特定寄存器或通过将其推入特定位置的堆栈来调用成员函数。构造函数在语言方面有点不寻常,但从ABI的角度来看,它们遵循这种模式。
通常,this
- 指针被视为函数的隐式第一个参数。例如,在正常的x86调用约定下,指向对象的指针位于" bottom" (堆栈的内存顺序)。成员变量本身不在堆栈上;这没有任何意义,因为构造函数(与其他成员函数一样)可能需要写入这些变量,而这些写入需要影响"真正的"对象的副本。因此,将指针推向它们。
答案 3 :(得分:0)
对象构造不仅仅涉及构造函数体的执行。首先,初始化所有基础子对象和成员子对象,只有然后才能运行构造体。因此,当为对象构造选择特定构造函数时,子对象构造函数首先运行,并且它们的参数由原始构造函数的初始化列表给出。之后,构造函数体运行,或多或少像普通函数一样,从构造函数参数填充参数。