Объявление вектора в качестве глобальной переменной в C ++ - PullRequest
12 голосов
/ 26 сентября 2011

Является ли хорошей практикой объявлять вектор глобальным в C ++?

Это то, что я сделал.

#include <vector>
std::vector<int> vec;

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

Пожалуйста, сообщите.

Ответы [ 6 ]

8 голосов
/ 26 сентября 2011

Моя программа успешно компилируется, но я не уверен, что это может приводить к ошибке во время выполнения при определенных обстоятельствах.

Это безопасно сделать; хранилище для переменной vec будет выделено статически, и ее конструктор по умолчанию будет вызываться в какой-то момент (именно тогда, когда в контексте всей вашей программы строго не определено, поскольку порядок инициализации между единицами перевода не является строго определенным).

и компилятор может зарезервировать ограниченный объем памяти, для которого это вектор может расширяться. При достижении этого предела то, что пишется, может есть в памяти, используемой другой переменной.

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

Все это говорит, что хотя это безопасно, это не обязательно хорошая практика; он попадает в область любой другой глобальной переменной или глобально доступного бита хранилища, что может быть предметом спора. Как правило, я бы посоветовал избегать глобальных переменных, как правило. Хотя в некоторых случаях это может быть приемлемо, глобальный доступ противоречит вашей способности контролировать доступ к переменной и применять к ней инварианты, а также состояние, которое они контролируют или подразумевают. Это может привести к сложностям в обслуживании систем в масштабах кодовой базы, поскольку эти пути доступа четко не прописаны.

4 голосов
/ 26 сентября 2011

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

Это неверное понимание.

Память не выделена во время компиляции.Память выделяется при запуске программы , а затем во время программы, в зависимости от типов переменных storage .И когда программа завершает работу, вся используемая ею память возвращается в ОС, несмотря ни на что.

При достижении этого предела записываемое содержимое может попасть в память, используемую другой переменной.

Нет.Объект std::vector<int> никогда не может съесть память , используемую другой переменной (ями).

Теперь вернемся к вашему основному вопросу:

Этохорошая практика объявить вектор глобальным в C ++?

Нет.Избегайте глобальных переменных, независимо от их типа.

3 голосов
/ 26 сентября 2011

Ну, vec - это глобальная переменная, поэтому память для нее предположительно выделяется из сегмента данных.Однако память для содержимого vec зависит от распределителя.По умолчанию я думаю, что память для содержимого выделяется из кучи.

3 голосов
/ 26 сентября 2011

Только пространство для векторных метаданных будет выделено в области для глобальных переменных.Содержимое вектора будет по-прежнему распределяться динамически (конструкторы и деструкторы обычно работают с глобальными переменными).

Такая же ситуация для автоматической векторной переменной, как:

int main(void)
{
    std::vector<int> v;
    return 0;
}

Существует ограничение дляпространство стека, доступное для автоматических переменных, но векторное содержимое не будет использовать это пространство, только несколько указателей и счетчиков.

2 голосов
/ 26 сентября 2011

Ваша программа ничего не выделяет во время компиляции - я думаю, вы имеете в виду время выполнения.

Вектор выделяет то, что он хранит в куче (vec.size () * sizeof (/ * что выудерживают * /)) - он содержит sizeof (std :: vector <>) в том месте, где он размещен.Глобальные переменные могут храниться где угодно, это зависит от реализации.

2 голосов
/ 26 сентября 2011

Глобальные переменные вообще плохая практика. Как вы говорите, они не «съедят» в памяти другую переменную, однако вам, программисту, очень легко что-то испортить. Например, все в программе имеет доступ к этому вектору, поэтому все могут получить к нему доступ и изменить его. Вы можете или не можете этого хотеть, но, скорее всего, вы этого не хотите.

Что касается распределения памяти, объекты, добавленные в вектор, все еще добавляются во время выполнения (потому что они не существуют во время компиляции!). Память также никогда не выделяется во время компиляции. Ваша программа имеет подпись для выделения этой памяти во время RUN. Подумайте об этом ... если бы программа выделяла память во время компиляции, вы бы не смогли запустить их на других машинах, не так ли? Память будет выделена на ВАШЕЙ машине, но не на других машинах. Следовательно, память должна быть выделена во время выполнения.

...