#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
в вашей второй фразе.