Вызов оператора нового в глобальном масштабе - PullRequest
2 голосов
/ 10 ноября 2011

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

int* g_pMyInt = new int;

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

Итак, я продолжил и попробовал:

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

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

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

Ответы [ 3 ]

6 голосов
/ 10 ноября 2011

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

int i = 5 + 6;

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

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

std::ostream & os(std::cout << "hello world\n");

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, была бы идеальным решением.

2 голосов
/ 10 ноября 2011

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

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

2 голосов
/ 10 ноября 2011

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

...