По первому вопросу: Когда компилятор встречает оператор 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
не будет делать этот вызов каждый раз, только когда он исчерпал память, которую он имеет в настоящее время.
По второму вопросу : Для локальных переменных это действительно зависит от компилятора. Стандарт не упоминает о стеке. Однако, скорее всего, вы работаете на общей архитектуре, работающей на общей ОС и использующей общий компилятор: -).
Таким образом, в случае common компилятор обычно резервирует место в начале вызова функции для всех локальных переменных, соответственно корректируя стек или резервируя для них регистры, если это возможно (регистр является предпочтительный выбор, поскольку он намного быстрее).
Затем (в c ++), когда переменная встретится, она вызовет конструктор. Теоретически, он может корректировать стек по мере необходимости, но это будет сложно доказать, что он правильный и менее эффективный. Обычно резервирование стекового пространства - это отдельная инструкция, поэтому выполнение всего этого за один раз довольно оптимально.