Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Чем плохи глобальные переменные? |
Автор: mrbrooks 9.10.2007, 08:51 |
Комрады. Наболело. Объясните чем плохи глобальные переменные. Уже сколько раз встречал - глобальная переменная это плохо. Пространство имен и все такое. А вот что бы научно - доходчиво - сразу молчок. Вотя я новичок. Глобальными стараюсь не пользоваться - ибо это ПЛОХО - но вот почему? Ведь с другой стороны это удобно. |
Автор: MAKCim 9.10.2007, 08:59 |
mrbrooks, ничего плохого в использовании глобальных переменных нет долой предрассудки надо просто все делать с умом и четко понимать конечную цель бывают случаи, когда без глобальных переменных не обойтись та же переменная errno глобальна я уж не говорю о стандартных stdin, stdout, stderr в многопоточном программировании глобальные переменные + средства синхронизации используются на ура если надо выделить статически большой кусок данных, то BSS + глобальный массив - лучшее и самое производительное решение |
Автор: Daevaorn 9.10.2007, 09:00 |
1. Невозможно контролировать время жизни, что ещё более страшно и предугадать время создания/удаления тоже нельзя. 2. Пораждают негибкую архитектуру |
Автор: Anikmar 9.10.2007, 09:02 |
Ну прям из серии плох ли goto. На мой взгляд ни одна серьезная программа без глобальных переменных просто не обойдется. Все должно контролироваться здравым смыслом. Глобальные переменные были есть и будут. Начиная от операционной системы. |
Автор: mrbrooks 9.10.2007, 09:09 |
А ну и славно. Я то уж было испужался - а оказывается не все так и плохо. После заявлений таких метров можно тему и прикрыть. ЗЫ. а goto хорош но в меру на мой начинающий взгляд. |
Автор: mrbrooks 9.10.2007, 09:21 |
Я убедился в одном - все можно - но в меру. Эврика!!! Но тем не менее я удовлетворен полученными мнениями. Что бы я без вас делал - наверно считал бы на калькуляторе!!! |
Автор: MAKCim 9.10.2007, 09:22 | ||||||
Fazil6, заметь, я не призывал использовать глобальные данные я лишь сказал, что ничего плохого в них нет, если использовать их по делу и с умом и привел примеры, где без них никак (или почти никак)
не определен, но при передаче управления в main() они уже инициализированы (до main выполняется куча кода по инициализации, секции .init, .text (до main)) Добавлено @ 09:25
ну что за обобщение? кто такое сказал? не все в нашей жизни ООП для каждой задачи свое решение и не всегда количество переменных со временем их жизни связано приведенным тобой соотношением Добавлено через 8 минут и 9 секунд вот пример
до main() тут дело даже не дойдет и нам здесь абсолютно побоку, порядок инициализации и прочие вещи а вот если мы попадаем в main(), это гарантирует, что инициализация всех глобальных бъектов прошла успешно |
Автор: Alek86 9.10.2007, 09:37 |
MAKCim, имелась в виду проблема порядка ИХ инициализации. При создании глобального объекта A я не могу быть уверен, что глобальный объект B, который у меня в A используется, уже создан. та проблема, которая описана у Майерса и решалась паттерном Синглтон (довольное неожиданное применения паттерна, кстати ![]() |
Автор: Lazin 9.10.2007, 10:01 | ||
Самоя большая проблема с глобальными переменными, при неправильном использовании, это то что неизвестно какое они имеют состояние
я однажды видел проект, в котором использовалось полсотни глобальных переменных вот в таком вот духе. Стоило поменять код в одном месте, начинало глючить в другом. Короче так глобальными переменными лучше не пользоваться. Помимо этого в многопоточных программах, глобальные переменные еще нужно синхронизировать(если это не int ![]() Если пишешь объектно ориентированную программу, то там у тебя будет минимум глобальных переменных, в случае если дизайн правильный. Ведь объекты должны обмениваться сообщениями, а не передавать информацию друг другу через глобальные переменные. |
Автор: Mihhail 9.10.2007, 11:41 |
Глобальными обычно назначаются переменные связанные с единственным параметром или свойством. Нужно исключать ситуации когда одна переменная меняет своё предназначетие от функции в функции, в таких случаях действитеьно возможна путаница и пересечение областей применения. Например для временного хранения однотипных значений можно дыло бы выделить одну глобальную переменную и использовать её во всех функциях, но при условии исключения взаимного вызова этих функций. |
Автор: maxim1000 9.10.2007, 12:14 | ||
есть некоторые аспекты, связанные с восприятием кода рассмотрим такую ситуацию
в этой строке есть три объекта: x,f,y здесь мы точно видим: изменяется x, y (если передан по неконстантной ссылке) и f (если это, например, объект с переопределённым operator() ) если эта функция изменяет глобальную переменную z, получается, что мы этого не видим нам нужно смотреть её код даже если функция f только читает содержимое z, всё равно в разных местах программы f(y) может возвращать разные значения для одного и того же y (т.к. она ещё и зависит от значения z) всё это не делает невозможным понимание кода, такие ситуации делают его просто немного труднее Добавлено через 2 минуты и 16 секунд или даже рассмотрим другую ситуацию: мы ловим баг, связанный с тем, что у переменной z устанавливается неправильное значение если она глобальная, это значение, в общем-то может установить любая функция так что сужая область видимости переменной мы сужаем область, которую нам придётся исследовать при ловле багов |
Автор: mrbrooks 9.10.2007, 12:18 |
Народ. Блин я думал я знал С++ хоть чуть чуть. Но после ваших высказываний - я понял - учиться мне еще учиться и еще раз учиться. ЗЫ. И в догонку еще раз учиться. |
Автор: maxim1000 9.10.2007, 12:22 |
есть даже более сильные рекомендации (которым лично я зачастую следую) [похоже, они пришли из области функционального программирования] строка x=f(y) должна менять только x, т.е. избегать передачи параметров по неконстантной ссылке это опять же позволяет сразу отсеять кучу мест, где может меняться "y", уже на этапе простого визуального "пробега" по коду (а именно - те, в которых "y" не стоит слева от знака равенства) |
Автор: Alexeis 9.10.2007, 12:24 |
И еще это засорение пространства имен. Я люблю когда все схожее называется одинаково. Глобальная область видимости мне не дает такой свободы, ведь каждый раз нужно придумывать всякие префиксы к именам, уж лучше написать класс / структуру. |
Автор: maxim1000 9.10.2007, 12:25 |
конечно же нужно понимать, что всё это - рекомендации, касающиеся только одного аспекта процесса восприятия кода, есть ещё и другие если использование глобальной переменной выглядит естественно и не вносит непонимания в код - надо использовать глобальные переменные если вносит непонимание, но уменьшает его эффективность - надо решать, что важнее |
Автор: Alexeis 9.10.2007, 12:27 |
Я стараюсь строить программу в виде восходящего дерева/деревьев. Т.е. в глобальной области один или несколько стволов, все остальное дочерние элементы. Так принято у борланда в VCL. Неплохая модель. |
Автор: maxim1000 9.10.2007, 12:32 | ||||
а кто мешает объявить глобальную переменную в соответствующем пространстве имён? (которые и были придуманы в частности для того, чтобы формализовать и развить всякие префиксы, которые люди придумывали для отражения области задач объектов) кроме того, глобальность и компоновка данных в структуры - в некотором смысле почти независимые понятия и со стековыми объектами можно встретить такое:
от того, что они стали локальными проблема с тем, что на них всегда надо смотреть в паре, никуда не пропала с другой стороны те же структуры тоже могут быть глобальными... |
Автор: Alexeis 9.10.2007, 12:42 | ||
Правильно. Но если рассуждать чисто логически, то переменная в пространстве имен уже не глобальная, она уже принадлежит определенной группе и доступ к ней уже не прямой. В этом смысле я слабо понимаю чем это лучше создания класса, ведь класс позволяет точно также спрятать переменную под крыло своего пространства имен. |
Автор: maxim1000 9.10.2007, 12:51 | ||||
суть в том, что он - открытый всем именно это я подразумевал под глобальностью пространства имён всего лишь организуют, но не контролируют доступ
ну а для класса там уже всё по-другому для доступа к переменной тогда нужен объект, который её содержит, значит, его нужно передать функции, а значит, он будет упомянут в строке (ну если, конечно, сам объект объявлен глобально, то снова появляется глобальная переменная, просто другого типа) |
Автор: SergeCpp 9.10.2007, 13:00 | ||
http://www.google.com/search?hl=en&q=%D0%9C%D0%B0%D0%BA%D0%BA%D0%BE%D0%BD%D0%BD%D0%B5%D0%BB%D0%BB+%D0%A1%D0%BE%D0%B2%D0%B5%D1%80%D1%88%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9+%D0%BA%D0%BE%D0%B4 (дороговата, но купите бумажную!) Добавлено через 3 минуты и 49 секунд
Я, к примеру, для этого использую namespace (с глобальными (уже не совсем и глобальными, выходит) inside) |
Автор: mrbrooks 9.10.2007, 13:20 | ||
Значит если я запихаю все свои глобальные данные в некую структуру и буду их там переваривать это есть выход из сложившейся ситуации. И уже по мере надобности я буду обращаться к ее элементам. Я правильно понял? |
Автор: maxim1000 9.10.2007, 14:43 | ||
структуры - способ собрать вместе данные, которые связаны по смыслу, отражают какую-то сущность глобальные-неглобальные - неважно так что это сильно зависит от "сложившейся ситуации" |
Автор: comcon1 9.10.2007, 15:47 | ||
Мда. а что, сбор в структуру как-то ограничит доступ к ним??? чтобы ограничить доступ, можно собирать их в приват отдельного объекта-синглетона и открывать доступ, например, только определенным классам. хотя какими способами наиболее корректно реализовать последнее... ![]() |
Автор: Alexeis 9.10.2007, 15:50 |
Конечно, для доступа нужно обращаться уже через точку/стрелочку, а не просто по имени. |
Автор: Dronchik 9.10.2007, 17:07 | ||||
Тогда уж лучше protected и делать друзей класса. |
Автор: archimed7592 9.10.2007, 18:16 | ||
А считает ли кто-нибудь плохой такую вот глобальную "переменную":
|
Автор: maxim1000 9.10.2007, 18:31 | ||
и не дай бог кому-то захотеть посчитать логарифм ![]() впрочем, это уже проблема макросов, а не глобальных переменных а журнальчик такой я и сам частенько делаю, так и использую
|
Автор: archimed7592 9.10.2007, 18:33 |
Ну это наглядности ради ![]() |
Автор: maxim1000 9.10.2007, 18:38 |
проблема препроцессора в его незнании о том, что такое C++ ![]() (в частности пространства имён и классы) какое бы осмысленное имя не дать этому define'у, найдётся программист, которому захочется так назвать метод своего класса, и если повезёт, всё закончится ошибкой компилятора... а сама журнализация - вполне нормальный пример того случая, когда глобальные переменные естественны, и ничего страшного их доступность всем не приносит... |
Автор: comcon1 10.10.2007, 11:00 |
Я б напиписал friend, если бы примерно год назад на форуме с такой же жестокостью не обсуждалась проблема "Чем плохи дружественные классы". |