Вызов оператора new в глобальной области видимости

#c #new-operator

#c #new-operator

Вопрос:

Мы с коллегой спорили о возможности компиляции при написании этого в глобальной области видимости:

 int* g_pMyInt = new int;
  

Мои аргументы вращались вокруг того факта, что вызов функции (которая new является)
в глобальной области видимости было невозможно. К моему удивлению, приведенная выше строка скомпилировалась просто отлично
(MS-VC8 и LLVM 3 от Apple).

Итак, я продолжил и попытался:

 int* foo()
{
    return new int;
}
int* g_pMyInt = foo(); // Still global scope.
  

И это также скомпилировалось и сработало как шарм (протестировано позже с классом
чей конструктор / деструктор распечатал сообщение. Сообщение ctor
прошел, dtor этого не сделал. На этот раз удивлен меньше.)

Хотя это кажется мне очень неправильным (нет упорядоченного / правильного способа / времени для вызова delete), это не запрещено компилятором. Почему?

Комментарии:

1. в чем именно проблема? Вы можете просто delete f_pMyInt , когда захотите.

2. Поскольку в глобальной области видимости есть операторы new и delete (и другие тоже), фактически вы можете перегрузить и их.

3. Где вы прочитали, что вызов функции в глобальной области видимости невозможен? Это серьезно неверное предположение

4. @drhirsch: Вот так: foo();

5. @AssafLevy: Вы не можете этого сделать, потому что у вас не может быть выражений в области пространства имен — foo(); это оператор expression. У вас могут быть объявления с инициализаторами в области пространства имен, и инициализатором может быть любое выражение с подходящим типом, включая вызов функции.

Ответ №1:

Почему это не должно быть разрешено? Все, что вы делаете, это инициализируете глобальную переменную, что вы вполне можете сделать, даже если инициализация включает вызов функции:

 int i = 5   6;

double j(std::sin(1.25));

const Foo k = get_my_foo_on(i, 11, true);

std::ostream amp; os(std::cout << "hello worldn");

int * p(new int);                // fine but very last-century
std::unique_ptr<int> q(new int); // ah, welcome to the real world

int main() { /* ... */ }
  

Конечно, вам нужно будет беспокоиться об удалении динамически выделяемых объектов, независимо от того, были ли они выделены в глобальной области видимости или нет … класс-оболочка, владеющий ресурсами, такой как unique_ptr , был бы идеальным решением.

Комментарии:

1. Время, в которое мы живем — люди не могут нести ответственность даже за выполнение вызова и хотят, чтобы их ограничивали. 😉

2. Ну, я думал, что main () всегда вызывается первым. Ты живешь, ты спрашиваешь, ты учишься 🙂 Спасибо.

3. @AssafLevy: Совсем наоборот. Если хотите, main() вызывается последним !

4. @AssafLevy: Обратите внимание, что это C -изм. В C инициализаторы не могут быть вызовами функций.

5. @GMan: Спасибо, вы правильно догадались, что это было частью путаницы.

Ответ №2:

C позволяет выполнять обработку до и после main функции, в частности, для статических объектов с конструкторами и деструкторами (их конструктор должен выполняться до main , их деструктор после него). И действительно, порядок выполнения не совсем четко определен.

Если вы используете GCC, смотрите также его атрибут функции constructor (который может помочь отдать приказ).

Комментарии:

1. Если быть точным, порядок выполнения внутри одной единицы перевода действительно четко определен (порядок объявления); но не для нескольких TU.

2. Означает ли это, что delete ptr; после main() завершения фигурная скобка будет вызываться после основных выходов?

3. Да. поскольку в приведенном выше примере он вызывается изнутри деструктора GLOBAL

Ответ №3:

Конечно, вы можете вызывать функции из глобальной области видимости, как часть инициализации глобальных объектов. Если бы вы не могли, вы не смогли бы определять глобальные переменные типов с помощью конструкторов, потому что конструкторы также являются функциями. Однако имейте в виду, что порядок инициализации между различными единицами перевода четко не определен, поэтому, если ваша функция полагается на глобальную переменную из другой единицы перевода, у вас возникнут проблемы, если вы не приняли особых мер предосторожности.

Комментарии:

1. Я думаю, вы имеете в виду you couldn't define _global_ variables в вашей второй фразе.