对于第一个问题:当new
编译器遇到运算符时,例如您的示例:
int * pData = new int[256];
它有效地发出如下代码:
int *pData = reinterpret_cast<int*>(::operator new(256 * sizeof(int)));
// the compiler may also choose to reserve extra space here or elsewhere to
// "remember" how many elements were allocated by this new[] so delete[]
// can properly call all the destructors too!
如果应该调用构造函数,那么也会发出(在这个例子中,我相信没有调用构造函数)。
operator new(std::size_t)
是一个由标准库实现的函数,通常但并非总是如此,它会归结为一个malloc
调用。
malloc
将不得不进行系统调用,以从操作系统请求内存。由于操作系统分配器通常使用较大的固定大小的内存块,malloc
因此不会每次都进行此调用,只有在它耗尽当前拥有的内存时才进行此调用。
对于第二个问题:对于局部变量,它确实取决于编译器。该标准没有提到堆栈。但是,您很可能处于运行通用操作系统并使用通用编译器的通用架构上:-)。
因此,对于常见情况,编译器通常会在函数调用开始时为所有局部变量保留空间,方法是相应地调整堆栈或为它们保留寄存器(如果可以)(寄存器是首选,因为它更快)。
然后(在c++中),当遇到变量时,它会调用构造函数。理论上,它可以根据需要调整堆栈,但这会很复杂,无法证明正确且效率较低。通常保留堆栈空间是一条指令,因此一次完成所有操作是非常理想的。