Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Религиозные войны > использовать ли глобальные переменные?


Автор: Proghat 12.4.2009, 18:21
Как лучше писать и почему?

I вариант:
Код

void rec( int sum, int n, int c ) {
  if ( sum == n ) {
  }
  for ( i = 1; i <= c; i++ ) {
    rec( sum + a[i], n, c )
  }
}

int main(){
  int n( 10 ), c( 23 );

  rec( 0, n, c );

  return( 0 );
}


II вариант:
Код

int n, c;

void rec( int sum ) {
  if ( sum == n ) {
  }
  for ( i = 1; i <= c; i++ )
    rec( sum + a[i] )
  }
}

int main(){
  n = 10;
  c = 23;

  rec( 0 );

  return( 0 );
}


Внутри rec() n и c не изменяются.

Автор: mes 12.4.2009, 18:27
Цитата(Proghat @  12.4.2009,  17:21 Найти цитируемый пост)
Как лучше писать и почему?

попробуйте написать хотя бы 10 подобных функций с их использованием в обоих вариантах, сравните и сами увидите ответ на Ваши вопросы этой темы.
 smile 

Автор: Proghat 12.4.2009, 18:32
Цитата
сравните и сами увидите ответ

Сравнивать по каким критериям? По времени работы, объему кода, занимаемой памяти?

Автор: NDQuattro 12.4.2009, 18:35
Используйте их только в крайних случаях. 
В их использовании таится возможность появления ошибок которые сложно выявить.

Автор: Proghat 12.4.2009, 18:49
Цитата(NDQuattro @ 12.4.2009,  18:35)
Используйте их только в крайних случаях.

Нужда в передачи массива - крайний случай?

Добавлено:
Указатели! : ). Извиняюсь.

Автор: zim22 12.4.2009, 18:54
Цитата(Proghat @  12.4.2009,  18:49 Найти цитируемый пост)
Нужда в передачи массива - крайний случай?

передавайте в качестве параметра функции указатель на массив
глобальные переменные - зло.

Автор: UniBomb 12.4.2009, 18:56
Меня всегда радовали подобные вопросы))) Всё зависит от множества факторов - от конкретной задачи, от конкретной платформы, от конкретных рук. Напри пр программировании микроконтроллеров глобальные переменные намного лучше скажем переменных static как в плане скорости выполнения, так и скорости выполнения.....

Автор: Soah 12.4.2009, 19:03
http://forum.vingrad.ru/forum/topic-200768/0.html

http://forum.vingrad.ru/topic-176175.html

Автор: Любитель 12.4.2009, 19:09
Цитата(UniBomb @  12.4.2009,  18:56 Найти цитируемый пост)
как в плане скорости выполнения, так и скорости выполнения..... 

Что-то в этом есть smile 

Автор: UniBomb 12.4.2009, 19:19
Любитель, ммм... имелось в виду "как в размере программы, так и в скорости выполнения"))) Просто как всегда пальцы работают быстрее мозга...

Автор: Lazin 13.4.2009, 11:43
вы очень сильно облегчите себе жизнь, если ваши ф-ии, по возможности, будут реентерабельными, то-есть результат должен зависеть только от параметров и ни от чего больше

Автор: UniBomb 13.4.2009, 12:16
Lazin, очень сложно такое сделать, если функции являются обработчиками прерываний, обработчиками собитий (связанных с приёмом программы сообщений ОСи), главных функций потоков....

Автор: GoldFinch 13.4.2009, 12:47
UniBomb, +1
везде где есть callback'и без глобальных переменных (в том или ином виде) не обойтись

Автор: Lazin 13.4.2009, 13:04
Цитата(UniBomb @  13.4.2009,  12:16 Найти цитируемый пост)
очень сложно такое сделать, если функции являются обработчиками прерываний, обработчиками собитий (связанных с приёмом программы сообщений ОСи), главных функций потоков.... 

про обработчики прерываний я согласен, а с остальным - нет

Цитата(GoldFinch @  13.4.2009,  12:47 Найти цитируемый пост)
везде где есть callback'и без глобальных переменных (в том или ином виде) не обойтись

Очень даже обойтись, с помощью правильного дизайна приложения smile 
К примеру, есть у тебя ф-я обратного вызова, которая вызывается при подключении нового клиента, ну так почему-бы не передать в эту ф-ю указатель(ссылку) на новое соединение, и на объект сервер, в общем, на все что может понадобиться этой ф-ии что-бы сделать свою работу?
Если нет ограничений на сигнатуру ф-ии, то можно делать все что угодно, если это какая-либо API ф-я то тут то-же не все потеряно, к примеру ф-я передаваемая в CreateThread должна получать указатель, через этот параметр можно передать все что угодно, GetQueuedCompletionStatus может получать два указателя, которые передаются в ф-ю пользователем и тд..

Автор: bsa 13.4.2009, 13:28
Интересно, а что делать в случае WndProc? Она объявлена как:
Код
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
И тут уж никуда указатель свой не сунуть... Вот и получается, необходимо, например, хранить map<HWND, MyClass*>, если окон много...

Lazin, а фотка симпатичной девушки на аватарке с какой периодичностью меняется?..

Автор: MAKCim 13.4.2009, 13:40
Цитата(Lazin @  13.4.2009,  13:04 Найти цитируемый пост)
про обработчики прерываний я согласен

а я и с обработчиками прерываний не согласен
реентерабельной функция может быть и при использовании глобальных данных  smile 

Автор: Lazin 13.4.2009, 13:56
Цитата(bsa @  13.4.2009,  13:28 Найти цитируемый пост)
Интересно, а что делать в случае WndProc? Она объявлена как:

Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

И тут уж никуда указатель свой не сунуть... Вот и получается, необходимо, например, хранить map<HWND, MyClass*>, если окон много...

я думал, что можно передать указатель на свой объект, через последний параметр ф-ии CreateWindow, хотя GDI не мой конек smile 

bsa, со случайной )

Автор: Любитель 13.4.2009, 14:02
GetWindowLong/SetWindowLong + GWL_USERDATA + hWnd.

Автор: Ln78 13.4.2009, 15:47
Цитата(Proghat @  12.4.2009,  19:21 Найти цитируемый пост)
Как лучше писать и почему?

I вариант:

код C++


void rec( int sum, int n, int c ) {
  if ( sum == n ) {
  }
  for ( i = 1; i <= c; i++ ) {
    rec( sum + a[i], n, c )
  }
}

int main(){
  int n( 10 ), c( 23 );

  rec( 0, n, c );

  return( 0 );
}


Proghat, а что это такое вообще? Просто лишь бы что-то было, или есть какой-то смысл именно в этом примере? В обоих вариантах примера используется непонятно где находящееся a[i], смысл if'а  в функции остался недоступен, других вариантов останова, кроме как по переполнению стека вызова я что-то не вижу. Что полезное делает это функция понять невозможно. Для данного примера ответ, ИМХО, зависит от того, какая цель преследуется. Если нужно, чтобы переполнение наступило быстрее, то дополнительные переменные этот процесс ускорят. Если нужно, чтобы подольше помучилась, то использование глобальных переменных немного продлит процесс. Что это за пример такой?  smile 

Автор: Proghat 13.4.2009, 15:55
Цитата(Ln78 @ 13.4.2009,  15:47)
Что это за пример такой?

Я привел не полный код.

Автор: Ln78 13.4.2009, 16:09
Цитата(Proghat @  13.4.2009,  16:55 Найти цитируемый пост)
Я привел не полный код. 

Так его или совсем не нужно было приводить, получается тема "за жисть поговорить", или как-то конкретизировать условия. Или думаешь, без этого примера никто не догадается чем отличается в коде использование глобальных переменных и передача переменных как параметров фукнции? 
Если хочешь, чтобы общий разговор на тему был полезен и тебе, можно было как-то хотя бы немного уточнить, на чём программируешь (С, С++), какой сложности программы писал, что на тему читал и т.д. А то ведь не всякий разговор воинов дZена понятен школьнику обыкновенному. 

Автор: Proghat 13.4.2009, 16:31
Цитата(Ln78 @  13.4.2009,  16:09 Найти цитируемый пост)
Так его или совсем не нужно было приводить, получается тема "за жисть поговорить", или как-то конкретизировать условия. Или думаешь, без этого примера никто не догадается чем отличается в коде использование глобальных переменных и передача переменных как параметров фукнции? 

Понятно. Учту ; ). Хотел спросить об использовании глобальных переменных именно в данном примере(это решение простой олимпиадной задачи).

Прочитал эту тему и те две темы, которые предлагал Soah и сделал для себя выводы:
1) всегда нужно стараться сделать функцию максимально независимой от другого кода;
2) в решении простой олимпиадной задачи (<100 строк) можно использовать глобальные переменные.

Цитата(Ln78 @  13.4.2009,  16:09 Найти цитируемый пост)
Если хочешь, чтобы общий разговор на тему был полезен и тебе, можно было как-то хотя бы немного уточнить, на чём программируешь (С, С++), какой сложности программы писал, что на тему читал и т.д. А то ведь не всякий разговор воинов дZена понятен школьнику обыкновенному. 

Учу C++. (До этого писал на Pascal около трех лет.) Писал решения олимпиадных задач.

Автор: vinter 13.4.2009, 17:12
Использование глобальных переменных нецелесообразно и опасно. Если дизайн поджимает и обойти никак, тогда лучше использовать функцию со static variable inside. Хотя бы избавит от несогласованности в инициализации между еденицами трансляции. В С++ я вообще не вижу в них смысла, если конечно не приходится в существующий  "дизайн" вписываться.

Автор: GoldFinch 13.4.2009, 17:42
Цитата(vinter @  13.4.2009,  18:12 Найти цитируемый пост)
Использование глобальных переменных нецелесообразно и опасно.

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

#include <intrin.h>
#pragma intrinsic(__rdtsc)

int g_RandSeed;

void randomize() {
    g_RandSeed=(int)__rdtsc();
}

int random(int lim) {
    g_RandSeed=g_RandSeed*0x8088405+1;
    return __int64(g_RandSeed*lim)>>32;
}

int main() {
    randomize();
    return random(10); 
}

Автор: mes 13.4.2009, 17:53
Цитата(GoldFinch @  13.4.2009,  16:42 Найти цитируемый пост)
в общем случае, это и целесообразно, и безопасно

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

Автор: vinter 13.4.2009, 17:54
Цитата(GoldFinch @  13.4.2009,  18:42 Найти цитируемый пост)
в общем случае, это и целесообразно, и безопасно

есть опыт работы с большими проектами?

Автор: GoldFinch 13.4.2009, 18:07
vinter, с небольшими, и не на С\С++
приведите пример, где использование глобальных переменных нецелесообразно и опасно, 
ато может то что очевидно вам, совсем не очевидно остальным


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

Автор: vinter 13.4.2009, 18:27
GoldFinch, конкретного примера под рукой нет. Но, потенциальные проблемы:
1. Проблемы связанные с сокрытием и перекрытием имен. Ужасные проблемы могут быть связаны с этим.
2. Проблемы меж-еденица-трансляционного взаимодействия - нет гарантии, что переменная инициализирована при ее использовании, нет гарантии что переменная не изменит своего значения в неподходящий момент.
Глобальную переменную в больших проектах, практически невозможно контролировать

Автор: Anikmar 13.4.2009, 18:35
Цитата(vinter @  13.4.2009,  18:27 Найти цитируемый пост)
Глобальную переменную в больших проектах, практически невозможно контролировать

Возьмем пример:
Некие настройки большого проекта - пара сотен окон, все хотят сохранить некие свои настройки.
1 подход. Сохраняйся кто как может. Используем налево-направо серализацию, плодим кучу веток в реестре или файлах настройки. Это все легко контролируется?
2 подход. Глобальный объект локальных настроек. Один на всех, который поддерживает необходимые методы для сохранения всего что кому-нибудь нужно.

Что легче контролировать?

У глобальных переменных есть только одна проблема: программист(-ы). Если разработчик(-и) дружат с головой ничего страшного в глобальных переменных нет.
ИМХО.

Автор: Lazin 13.4.2009, 18:37
Цитата(GoldFinch @  13.4.2009,  18:07 Найти цитируемый пост)
приведите пример, где использование глобальных переменных нецелесообразно и опасно

самый простой пример - масштабируемость кода, допустим есть у нас глобальая переменная connection, мы ее юзаем в множестве мест программы, все хорошо, не нужно передавать лишних параметров в методы(ф-ии), достаточно проверить if (connection.connected()) и все, программа растет и обрастает функционалом, и тут выясняется что дальше нам прийдется работать с большим количеством connection-ов, либо с connection-ом другого типа smile 

Автор: vinter 13.4.2009, 18:52
Цитата(Anikmar @  13.4.2009,  19:35 Найти цитируемый пост)
2 подход. Глобальный объект локальных настроек. Один на всех, который поддерживает необходимые методы для сохранения всего что кому-нибудь нужно.

почему некий внешний объект должен хранить локальные настройки окна? Это не верно. Есть некие глобальные настройки, их можно сделать через глобально доступный синглтон. Но уж никак не делать глобальную переменную.

Автор: GoldFinch 13.4.2009, 19:03
Цитата(Lazin @  13.4.2009,  19:37 Найти цитируемый пост)
самый простой пример - масштабируемость кода, допустим есть у нас глобальая переменная connection, мы ее юзаем в множестве мест программы, все хорошо, не нужно передавать лишних параметров в методы(ф-ии), достаточно проверить if (connection.connected()) и все, программа растет и обрастает функционалом, и тут выясняется что дальше нам прийдется работать с большим количеством connection-ов, либо с connection-ом другого типа

и каково же решение этой проблемы?
чем например
extern Сonnection_t connection;
отличается от
class SomeNiceSingleton ... {
  ...
  Сonnection_t connection;
  ...
}

Добавлено через 1 минуту и 33 секунды
Цитата(vinter @  13.4.2009,  19:52 Найти цитируемый пост)
Есть некие глобальные настройки, их можно сделать через глобально доступный синглтон. Но уж никак не делать глобальную переменную. 

чем глобальный тип (класс) лучше глобальной переменной?

Автор: MAKCim 13.4.2009, 19:07
Цитата(Lazin @  13.4.2009,  18:37 Найти цитируемый пост)
и тут выясняется что дальше нам прийдется работать с большим количеством connection-ов, либо с connection-ом другого типа

передавать адрес connection в каждую функцию его использующую религия не позволяет?  smile 

Автор: Любитель 13.4.2009, 19:08
MAKCim, так это будут самые что ни есть неглобальные переменные. Обычный инстан-метод по сути.

Автор: vinter 13.4.2009, 19:17
Цитата(GoldFinch @  13.4.2009,  20:03 Найти цитируемый пост)
чем глобальный тип (класс) лучше глобальной переменной?

1. Нет проблемы имен.
2. Нет проблемы с меж-еденица-трансляционным взаимодействием.
3. При небольшой модификации нет проблем с межпроцессным взаимодействием 

Автор: Lazin 13.4.2009, 21:02
Цитата(GoldFinch @  13.4.2009,  19:03 Найти цитируемый пост)
и каково же решение этой проблемы?

такое
Цитата(MAKCim @  13.4.2009,  19:07 Найти цитируемый пост)
передавать адрес connection в каждую функцию его использующую

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

Цитата(GoldFinch @  13.4.2009,  19:03 Найти цитируемый пост)
чем например
extern Сonnection_t connection;
отличается от
class SomeNiceSingleton ... {
  ...
  Сonnection_t connection;
  ...
}

возможностью управлять временем жизни синглтона, в отличии от глобальной переменной

Цитата(MAKCim @  13.4.2009,  19:07 Найти цитируемый пост)
религия не позволяет?

позволяет, если что, это был антипример smile 

Автор: zim22 13.4.2009, 21:27
Пару фраз вырвал из книги. Полный текст статьи занимает 2-3 страницы.
С.Х.Дьюхерст. Скользкие места С++.

Цитата

Совет 3. Глобальные переменные:
1) затрудняют повторное использование и сопровождение кода
2) увеличивают число зависимостей между компонентами
Пытаясь обосновать использование глобальных переменных, часто говорят, что они мол, удобны.
Это иллюзорный или эгоистический аргумент, поскольку сопровождение программы обычно продолжается дольше, чем первоначальная разработка.
Избегайте использования глобальных переменных. Для достижения тех же результатов имеются более безопасные и гибкие механизмы.

Автор: Anikmar 13.4.2009, 21:31
Цитата(vinter @  13.4.2009,  18:52 Найти цитируемый пост)
Есть некие глобальные настройки, их можно сделать через глобально доступный синглтон.

А чем синглтон принципиально отличается от глобальной переменной?

Под глобальной переменной я, например, понимаю не только обычную переменную типа int GlobalIntA, но и объект какого-либо класса, доступный из любого модуля проекта. Какая разница? Доступ через интерфейсные функции? Так и к обычной глобальной переменной можно через интерфейс доступ организовать.

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

Это мое ИМХО, естественно, я достаточно часто использую глобальные переменные когда они мне удобнее и никаких неудобств пока не ощутил. Правда, если бы я сделал глобальной переменную int i - я думаю ощутил бы некоторые неудобства, но для этого на плечах должно быть не только устройство для приема пищи и просмотра телевизора.
ИМХО.

Автор: Lazin 13.4.2009, 21:49
Цитата(Anikmar @  13.4.2009,  21:31 Найти цитируемый пост)
Под глобальной переменной я, например, понимаю не только обычную переменную типа int GlobalIntA, но и объект какого-либо класса, доступный из любого модуля проекта. Какая разница? Доступ через интерфейсные функции? Так и к обычной глобальной переменной можно через интерфейс доступ организовать.

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

Автор: Cтpaнник 13.4.2009, 21:54
[QUOTE=Anikmar,13.4.2009,  21:31]
Цитата(vinter @  13.4.2009,  18:52 Найти цитируемый пост)
Это мое ИМХО, естественно, я достаточно часто использую глобальные переменные когда они мне удобнее и никаких неудобств пока не ощутил.

А каков размер проекта (в тыс. LOC) и сколько в нем разработчиков?

Автор: Rififi 13.4.2009, 22:01
Proghat, 
Как лучше писать 
первым способом

и почему?
чтобы не прослыть ламером :eek: :gigi:

Автор: Anikmar 13.4.2009, 22:12
Цитата(Cтpaнник @  13.4.2009,  21:54 Найти цитируемый пост)
А каков размер проекта (в тыс. LOC) и сколько в нем разработчиков? 

Что такое LOC?
У меня варианты:
Чистящие средства: http://www.amway.ru/catalog?category=1094
Влажные салфетки: http://aukro.bigmir.net/item589863303-loc-vlazhnye-ochishchayushchie-salfetki.html
Библиотека конгресса США: http://www.loc.gov/index.html

Да не подумайте, что я распространяю СПАМ. Про аббревиатуры уже был разговор. Я не знаю, что такое LOC. Вы имеете в виду кол-во строк? Модулей?

Отвечаю: Размер проекта в LOC-ах примерно по 50К на ШКРАБа  smile 

Автор: Lazin 13.4.2009, 22:23
Lines Of Code

Автор: Fazil6 13.4.2009, 22:26
Цитата(GoldFinch @  13.4.2009,  19:03 Найти цитируемый пост)
чем глобальный тип (класс) лучше глобальной переменной?

тем, что поддерживать нужно только интерфейс. 
Используя глобальную переменую мы связываем между собой код, который ею пользуется. 
Сопровождать придется либо внутри " глобального типа" (что проще) либо по всему коду, где глобальная переменная используется
Цитата(Anikmar @  13.4.2009,  21:31 Найти цитируемый пост)
Под глобальной переменной я, например, понимаю не только обычную переменную типа int GlobalIntA, но и объект какого-либо класса, доступный из любого модуля проекта. Какая разница? Доступ через интерфейсные функции? Так и к обычной глобальной переменной можно через интерфейс доступ организовать.Вопрос не в том как это назвать и во что обернуть. Важно то, что существует некий объект (один на проект), состояние которого можно изменить из многих мест в проекте. Т.е. глобальный объект. И какая религия мешает использовать такие объекты (переменные) лично я не понимаю. Зачем вертеться ужом на сковородке только из-за того, что кто-то сказал, что глобальные переменные использовать не надо.

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

Цитата(zim22 @  13.4.2009,  21:27 Найти цитируемый пост)
Избегайте использования глобальных переменных. Для достижения тех же результатов имеются более безопасные и гибкие механизмы.

согласен. И совсем не нужно для этого вертеться ужом.

Автор: Anikmar 13.4.2009, 23:12
Цитата(Lazin @  13.4.2009,  21:49 Найти цитируемый пост)
синглтон - это когда объект некоторого типа, один на все приложение, и другой такой-же создать нельзя, это не то-же самое что и глобальная переменная   

Ну? Глобальная переменная некого типа тоже одна на все приложение и вторую такую-же создать нельзя. Ведь переменная типа "Класс_сингл_тон" одна? - Да. Она глобальная? - Да. В чем ее принципиальная разница от переменной не класса  "Класс_сингл_тон"?

Цитата(Fazil6 @  13.4.2009,  22:26 Найти цитируемый пост)
тем, что поддерживать нужно только интерфейс. 
Используя глобальную переменую мы связываем между собой код, который ею пользуется. 
Сопровождать придется либо внутри " глобального типа" (что проще) либо по всему коду, где глобальная переменная используется


Что значит сопровождать внутри кода? А если поменяем интерфейс - его не надо будет сопровождать внутри кода? Чем отличается сопровождение вызовов интерфейса? К глобальной переменной можно также сделать функции доступа по типу интерфейса. Просто если разделять два понятия как разные - тогда все понятно, но лично для меня они принципиально одинаковые:

Код

Вариант 1.

Определение
int AGlobal;
int BGlobal;

Объявление
extern int AGlobal;
extern int BGlobal;

Использование
AGlobal = 5;
BGlobal = 6;


Вариант 2:
Определение
MyGlobalClass ABC_Global;

Объявление
class MyGlobalClass // Можно синглтон, можно интерфейсные методы какая принципиальная разница?
{
public:
  int AGlobal;
  int BGlobal;
}

extern MyGlobalClass ABC_Global;

Использование:
ABC_Global.AGlobal = 5;
ABC_Global.BGlobal = 6;


Цитата(Lazin @  13.4.2009,  22:23 Найти цитируемый пост)
Lines Of Code 
 Мда. Я это подозревал, но не думал, что так просто. Думал - некая величина, оценивающая объем проекта  smile 

Строк кода - не знаю сколько (хотел посчитать, но что-то простого инструмента не смог найти, чтобы сразу в каталоге и во всех вложенных посчитать кол-во строк CPP и H). Проект небольшой, сразу скажу. По поводу кол-ва человек - этот проект чисто мой (пока). Сейчас просто я немного другими делами занимаюсь. Если подскажете простой способ (без написания программки подсчета - лень) я скажу сколько строк сейчас проект.

Одно время работал в команде, где было человек 15 и проекты были намного солиднее. И глобальные переменные использовали, и никто не путался, и проблем не было. Видимо потому, что начальство было отличное и ТЗ проработанные и взаимодействие отлажено.

Автор: Lazin 14.4.2009, 05:53
Цитата(Anikmar @  13.4.2009,  23:12 Найти цитируемый пост)
Ну? Глобальная переменная некого типа тоже одна на все приложение и вторую такую-же создать нельзя. Ведь переменная типа "Класс_сингл_тон" одна? - Да. Она глобальная? - Да. В чем ее принципиальная разница от переменной не класса  "Класс_сингл_тон"?

глобальная переменная
Код

MyClass global1, global2;

синглтон
Код

MyClass::instance()->mymethod();

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

Автор: Anikmar 14.4.2009, 07:29
Цитата(Lazin @  14.4.2009,  05:53 Найти цитируемый пост)
чувствуешь разницу?
время жизни глобальной переменной не определено, можно созданть множество объектов и тд..
синглтон это вообще совершенно другое, это не замена глобальных переменных, если у нас что-то в программе должно-быть доступно в разных еденицах трансляции это не синглтон, синглтон, это когда объект некоторого типа может быть создан только в одном экземпляре, например лог-файл, или файл конфигурации... 


Опять-таки скажу, что особой разности не вижу. Объект синглтона естественно один, но никто не мешает натыкать разных классов-синглтонов, как и не мешает натыкать глобальных переменных. Так что остаюсь при своем мнении - главное не как обозвать глобальный объект и во что его обернуть, а как его организовать и как с ним работать. Суть глобального объекта и объекта синглтона одинакова. Последний, согласен, более защищен от неправильных действий, но все равно сам объект остается глобальным, а то что скрыт за вызовом метода - также можно скрыть и обычный объект, если не объявлять его extern, а доступаться через некий глобальный интерфейс. К тому же предел паранойи должен быть - я понимаю защиту от дураков-пользователей, но защиту от дураков- программистов собственной команды нужно организовывать методом увольнения оных. ИМХО.

У меня глобальный объект настройки вынесен в отдельный модуль, который линкуется к каждому проекту в виде библиотеки. Из проекта требуется вызвать метод Init для его инициализации, а дальше через интерфейсные методы получать/сохранять необходимую информацию. Я пока не увидел никаких особых проблем - если объект хорошо документирован и есть инструкция, то никакой опасности нет.

Ну а с дури и болт сломать можно.
ИМХО.

Автор: Lazin 14.4.2009, 08:14
а синглтон разве обязан быть глобальным?
конечно любой глобальный объект это гвоздь в гроб масштабируемости кода, и множество разных синглтонов используемых глобально в проекте это плохо, но еще хуже использование глобальных переменных, так как в примере ТС-а


Цитата(Anikmar @  14.4.2009,  07:29 Найти цитируемый пост)
У меня глобальный объект настройки вынесен в отдельный модуль, который линкуется к каждому проекту в виде библиотеки. Из проекта требуется вызвать метод Init для его инициализации, а дальше через интерфейсные методы получать/сохранять необходимую информацию. Я пока не увидел никаких особых проблем - если объект хорошо документирован и есть инструкция, то никакой опасности нет.

если этот глобальный объект хранит конфигурацию приложения, то это нормально, так как конфигурация приложения редко меняется

Автор: GoldFinch 14.4.2009, 08:25
Цитата(Lazin @  14.4.2009,  09:14 Найти цитируемый пост)
еще хуже использование глобальных переменных, так как в примере ТС-а

если говорить о примере ТСа, то там применение глобальных переменных совершенно оправдано, т.к. прога маленькая
кроме того оно неплохо преобразуется в такой код:
Код

class Rec {
  int n, c;
  Rec();
public:
  Rec(int n_,int c_):n(n_),c(c_){}
  void operator() ( int sum ) {
    if ( sum == n ) {
    }
    for ( i = 1; i <= c; i++ )
      rec( sum + a[i] )
    }
  }
}
int main(){
  Rec rec(10, 23);
  rec( 0 );
  return( 0 );
}

Автор: MAKCim 14.4.2009, 08:50
Цитата(Любитель @  13.4.2009,  19:08 Найти цитируемый пост)
так это будут самые что ни есть неглобальные переменные. Обычный инстан-метод по сути. 

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

Автор: Remiznik 14.4.2009, 16:13
сразу скажу что больших проетков не писал, но мнение по этому поводу есть !

Для меня какждая функция должна быть универсальной, то есть может как можно чаше использоваться и даже быть пересена в другой проект так как это очень удобно написал одну функцию и юзаешь( конечно это почти не возможно но нужно стремиться ) . А при использованиии глобальных переменых это невозможно.
И потом наверно я не слишком умён чтоб отследить все изменения глобальной переменной в процессе работы программы ведь если есть даже пара функций с изменением глоб.пер. и они часто используетться не так просто это сделать !

Автор: zim22 14.4.2009, 16:19
Цитата(Remiznik @  14.4.2009,  16:13 Найти цитируемый пост)
 очень удобно написал одну функцию и юзаешь( конечно это почти не возможно 

а как же функции из STL?

Автор: Remiznik 14.4.2009, 16:46
а что STL ? я использую STL но причом тут глоб.перемен ?

Автор: Anikmar 14.4.2009, 16:47
Цитата(Lazin @  14.4.2009,  08:14 Найти цитируемый пост)
если этот глобальный объект хранит конфигурацию приложения, то это нормально, так как конфигурация приложения редко меняется 

Я с начала спора говорил - все от конкретики зависит и полностью отказываться от глобальных переменных себе же дороже.

Цитата(Remiznik @  14.4.2009,  16:13 Найти цитируемый пост)
 А при использованиии глобальных переменых это невозможно.

Если каждая функция будет использовать глобальные переменные для своей внутренней работы - в топку такой код.

Цитата(Cтpaнник @  13.4.2009,  21:54 Найти цитируемый пост)
А каков размер проекта (в тыс. LOC) и сколько в нем разработчиков? 

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

Автор: zim22 14.4.2009, 16:49
Цитата(Remiznik @  14.4.2009,  16:46 Найти цитируемый пост)
а что STL ? я использую STL но причом тут глоб.перемен ?

в том то и дело, что функции STL не нуждаются в глобальных переменных.

Автор: GoldFinch 14.4.2009, 17:45
zim22, и много их там, функций STL? 20?

Автор: vinter 14.4.2009, 19:04
Цитата(GoldFinch @  14.4.2009,  18:45 Найти цитируемый пост)
zim22, и много их там, функций STL? 20?

мдя.. открой да посмотри, и не позорься.
Цитата(Anikmar @  14.4.2009,  17:47 Найти цитируемый пост)
в крупных проектах использовали глобальные объекты без всякого вреда для проекта и психики команды.

код с глобальными переменными не пройдет ревью ни у одного здравомыслящего программиста.

Автор: zim22 14.4.2009, 19:19
Цитата(GoldFinch @  14.4.2009,  17:45 Найти цитируемый пост)
 и много их там, функций STL? 20?

60 штук  smile 

Автор: vinter 14.4.2009, 19:48
zim22, ~100

Автор: zim22 14.4.2009, 19:54
Цитата(vinter @  14.4.2009,  19:48 Найти цитируемый пост)
~100

нет. извольте, но я настою на своём.

Страуструп. Язык программирования С++. Специальное издание. Глава 18.
Цитата

18.2. На первый взгляд может показаться, что алгоритмов стандартной библиотеки несметное число. Однако их всего 60.



Автор: GoldFinch 14.4.2009, 20:14
cin, cout, cerr  - глобальные переменные?

Автор: mes 14.4.2009, 20:15
Цитата(Anikmar @  14.4.2009,  15:47 Найти цитируемый пост)

Я с начала спора говорил - все от конкретики зависит и полностью отказываться от глобальных переменных себе же дороже.

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

Код

void f(char *, int size) { .. }

int arry_size; // <-
void (char *) { .. }

тоже но с меньшим уроном проявляется и в циклах
Код

int i=0; for (;i<..;) .. 

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

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

Все вышесказанное имхо, проверенное на горьком опыте smile




Автор: Lazin 14.4.2009, 20:24
Цитата(GoldFinch @  14.4.2009,  20:14 Найти цитируемый пост)
cin, cout, cerr  - глобальные переменные? 

да, но тебя как правило не заботит то, что туда записывали раньше, так-что не в счет smile 

Автор: vinter 14.4.2009, 20:39
Цитата(zim22 @  14.4.2009,  20:54 Найти цитируемый пост)
нет. извольте, но я настою на своём.

Передо мной лежит книга, где среди авторов есть Meng Lee и Alexander Stepanov и вот там перечислено около 100 ф-ий. Эти ребята в STL по авторитетней будут ;)
Страуструп не прав полностью, в algorithm 66 ф-ий(если я не обсчитался). Но в STL есть не только algorithm

Автор: GoldFinch 14.4.2009, 23:00
Цитата(Lazin @  14.4.2009,  21:24 Найти цитируемый пост)
но тебя как правило не заботит то, что туда записывали раньше, так-что не в счет

значит всетаки есть глобальные переменные которые не в счет?)

Автор: mes 14.4.2009, 23:10
Цитата(GoldFinch @  14.4.2009,  22:00 Найти цитируемый пост)
значит всетаки есть глобальные переменные которые не в счет?) 

повторюсь : не сама глобальная переменная - зло, а 
Цитата(mes @  14.4.2009,  19:15 Найти цитируемый пост)
 ее применение не по назначению

или не к месту.

и типа правило: если можно не делать переменную глобальной, лучше не делать.
 smile 

Автор: Lazin 14.4.2009, 23:11
Цитата(GoldFinch @  14.4.2009,  23:00 Найти цитируемый пост)
значит всетаки есть глобальные переменные которые не в счет?) 

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

Автор: J0ker 14.4.2009, 23:14
Цитата(GoldFinch @  14.4.2009,  23:00 Найти цитируемый пост)
значит всетаки есть глобальные переменные которые не в счет?) 

а кто вам сказал, что это переменные? вы им попробуйте что-нить присвоить хыхыхы  smile 

Автор: Dmi3ev 14.4.2009, 23:19
 smile 
опять тема, которая заставляет форумчан философствовать и спорить... Мое мнение совпадает с мнением mes-а в предыдущем посте, считаю, что другого быть не может, хотя может, но мне кажется, что оно неверно, + к этому постоянно в книгах встречается это (причем с примером, почему лучше, и примеры бывают разные, самый распространенный, по-моему, это то, что можно работать с локальной, думая, что работаешь с глобальной, и получать неразбериху). Я воспринимаю это, как правило... Может я и не прав, так считаю я, и спорить не хочу...  smile   

Автор: Любитель 15.4.2009, 00:15
Цитата(Lazin @  14.4.2009,  23:11 Найти цитируемый пост)
такие вещи как стандартные потоки ввода-вывода не создают проблемм(хотя они все-же имеют состояние и это иногда создает проблемы)

Вот именно. Изменитт кто-нибудь форматирование в потоке, а ты потом думай... ИМХО это одна из ошибок дизайна стандартной библиотеки С++.

Автор: azesmcar 15.4.2009, 08:31
Цитата

а кто вам сказал, что это переменные? вы им попробуйте что-нить присвоить хыхыхы  smile  

Это переменные
Цитата

namespace std {
   extern istream cin;
   extern ostream cout;
   extern ostream cerr;
   extern ostream clog;
   ...
}

из стандарта С++. И то что им нельзя ничего присвоить еще не значит что они константны  smile
оператор присваивания это только один из способов изменить обьект. 
Цитата

Вот именно. Изменитт кто-нибудь форматирование в потоке, а ты потом думай... ИМХО это одна из ошибок дизайна стандартной библиотеки С++.

smile согласен

Автор: Anikmar 15.4.2009, 08:46
Вот так рождаются баяны. И все из-за того, что кто-то взял на себя ответственность высказать абсалютное мнение. 

Глобальные переменные - ЗЛО
Дефайн - ЗЛО
goto - ЗЛО

Все в этом мире может быть ядом, а может быть лекарством. Все зависит от дозы.

Ничего злого в глобальных переменных нет. Зло только в способе их применения.

Автор: azesmcar 15.4.2009, 08:49
Anikmar

да, тему надо перенести в религиозные войны smile 

Автор: Anikmar 15.4.2009, 08:53
Цитата(azesmcar @  15.4.2009,  08:49 Найти цитируемый пост)
Anikmar

да, тему надо перенести в религиозные войны   


На 100% согласен  smile 

Автор: Lazin 15.4.2009, 08:54
Цитата(Anikmar @  15.4.2009,  08:46 Найти цитируемый пост)
Ничего злого в глобальных переменных нет. Зло только в способе их применения. 

ну я даже не знаю что еще можно сказать
Чем меньше у тебя разные части приложения зависят друг от друга, тем лучше, глобальные переменные этому не способствуют. Так понятнее?

Автор: Anikmar 15.4.2009, 08:58
Цитата(Lazin @  15.4.2009,  08:54 Найти цитируемый пост)
Чем меньше у тебя разные части приложения зависят друг от друга, тем лучше, глобальные переменные этому не способствуют. Так понятнее? 


Если использовать термин "зависят" - вы правы. А если использовать термин "взаимодействуют" - то глобальные переменные способствуют этому. Нужно найти золотую серединку, а не ходить по краю.

Автор: mes 15.4.2009, 09:18
Цитата(Anikmar @  15.4.2009,  07:46 Найти цитируемый пост)
И все из-за того, что кто-то взял на себя ответственность высказать абсалютное мнение. 

Скорей всего из за того, что кто услышав эти выражения принял за абсолют.
Например  выражение  : змеиный яд - смертелен для человека. ( Однако он присутсвует в большом ряде лекарств. )
Также как : витамины - приносят пользу. ( Однако принятие большого кол-ва  ведет к отравлению. )
Они не абсолютны, но зачастую использование пояснения опускается, потому что оно известно обоим сторонам или в данном рассмотрении не столь важно.

Цитата(Anikmar @  15.4.2009,  07:46 Найти цитируемый пост)
Глобальные переменные - ЗЛО
Дефайн - ЗЛО
goto - ЗЛО

Радиация - зло.
Однако сколько ее применений во благо! Но от этого оно не перестает быть злом.

 smile 


Автор: Rickert 15.4.2009, 09:20
Третья тема однако, чем всё закончилось? smile 

Автор: Anikmar 15.4.2009, 09:28
mes, я с вами полностью согласен  smile 

Цитата(Rickert @  15.4.2009,  09:20 Найти цитируемый пост)
Третья тема однако, чем всё закончилось?   

Хорошие победили плохих и воцарился мир на земле  smile 


Автор: mes 15.4.2009, 09:28
Цитата(Anikmar @  15.4.2009,  07:58 Найти цитируемый пост)


Если использовать термин "зависят" - вы правы. А если использовать термин "взаимодействуют" - то глобальные переменные способствуют этому. Нужно найти золотую серединку, а не ходить по краю. 

знаете, понятие "зло" в обычной жизни используется для обучения ребенка.
Ток - зло. В розетку нельзя совать руки.
Спички -зло. Можно поджечь или обжечься.

Взрослый (нормальный) человек понимает что и как надо использовать в принципе не нуждается в образах.
Ему в голову не придет засунуть руку в кипяток, и использует его чтоб заварить чай.
Хотя скелет нарисованный на трансформаторах высокого напряжение с надписью "не входить" предназначен и для взрослых.
Однако элекрик входит и производит нужные работы.

Т.е. любое выражение надо воспринимать в контексте его высказывания и учитывать, что (практически) всегда есть недоговоренность, которую по каким то причинам сейчас не важна.
 smile

Добавлено через 2 минуты и 40 секунд
 smile 
Цитата(Anikmar @  15.4.2009,  08:28 Найти цитируемый пост)
Хорошие победили плохих и воцарился мир на земле  smile 

Хорошие на свой взгляд определили, кто плохие. Начали против них войну. И победив установили мир. На то они и хорошие.  smile 

Автор: Anikmar 15.4.2009, 09:39
 smile 
Цитата(mes @  15.4.2009,  09:28 Найти цитируемый пост)
Хорошие на свой взгляд определили, кто плохие. Начали против них войну. И победив установили мир. На то они и хорошие.    


Фразу я написал глядя на подпись под аватаркой Rickert-а  smile 

Автор: J0ker 15.4.2009, 21:23
Цитата(mes @  15.4.2009,  09:28 Найти цитируемый пост)
знаете, понятие "зло" в обычной жизни используется для обучения ребенка.

а я тут это использую
итак, дети:
Глобальные переменные - ЗЛО
Дефайн - ЗЛО
goto - ЗЛО
спички детям не игрушка  smile 

Автор: Rickert 16.4.2009, 02:29
J0ker, define зло? 
Всё, это последняя остановка, народ. Скоро половину языка назовут злом. Ну и не используй smile 
Это как господь дал тебе руки и ноги, а ты сказал, что их слишком много и половины себя лишил. Зачем - сам не понял.

Автор: Lazin 16.4.2009, 05:35
Rickert, 
Код

#define sizeof(x) rand()
 smile 

Автор: vinter 16.4.2009, 05:44
Цитата(Rickert @  16.4.2009,  03:29 Найти цитируемый пост)
J0ker, define зло? 

еще какое

Автор: MAKCim 16.4.2009, 08:09
дефайн не зло в принципе, поскольку с помощью него можно определять не только константы
готу не зло в С
глобальные переменные не зло в принципе

_основная_ цель программирования - получить программу, выполняющую нужные функции, эффективность и пр - это уже второй и пр. вопросы
вы уверены, что глобальные переменные во всех случаях этому не способствуют?

Автор: azesmcar 16.4.2009, 08:15
Код

#ifndef TYPELIST_H_
#define TYPELIST_H_

#define TYPELIST_1(x)           Typelist< x, NullType>
#define TYPELIST_2(x, y)        Typelist< x, TYPELIST_1(y)>
#define TYPELIST_3(x, y, z)     Typelist< x, TYPELIST_2(y,z)>
#define TYPELIST_4(x, y, z, w)  Typelist< x, TYPELIST_3(y,z,w)>

//...
#endif

какой злой код.
Цитата

готу не зло в С

 smile 
на тему гото дискуссия была уже

Автор: Lazin 16.4.2009, 08:58
Цитата(azesmcar @  16.4.2009,  08:15 Найти цитируемый пост)
#ifndef TYPELIST_H_
#define TYPELIST_H_
#define TYPELIST_1(x)           Typelist< x, NullType>
#define TYPELIST_2(x, y)        Typelist< x, TYPELIST_1(y)>
#define TYPELIST_3(x, y, z)     Typelist< x, TYPELIST_2(y,z)>
#define TYPELIST_4(x, y, z, w)  Typelist< x, TYPELIST_3(y,z,w)>
//...
#endif

и не лень? smile 

Код

template<class Head, class Tail>
struct TypeList
{
    typedef Head head_type;
    typedef Tail tail_type;
    Head value;
};
struct none {};

template< BOOST_PP_ENUM_PARAMS(4, class T)>
struct tuple;

#define TUPLE_PRINT(z, n, data) data

#define GEN_TUPLE(z, n, unused)                                 \
  template <BOOST_PP_ENUM_PARAMS(n, class T)>                   \
  struct tuple<                                                 \
      BOOST_PP_ENUM_PARAMS(n,T)                                 \
      BOOST_PP_COMMA_IF(n)                                      \
      BOOST_PP_ENUM(                                            \
          BOOST_PP_SUB(40,n), TUPLE_PRINT, none)                 \
  >                                                             \
{                                                               \
    typedef BOOST_PP_ENUM_PARAMS(n, TypeList<T), none           \
    BOOST_PP_REPEAT(n, TUPLE_PRINT, > ) type;                   \
};

BOOST_PP_REPEAT_FROM_TO(1, 40, GEN_TUPLE, ~)
#undef TUPLE_PRINT
#undef GEN_TUPLE



Добавлено через 2 минуты и 33 секунды
Код

tuple<int, char, double, long, Foo, Bar> mytuple;//до 40

Автор: azesmcar 16.4.2009, 09:01
Цитата

и не лень? smile 

кому? smile
Цитата

struct none {};
template< BOOST_PP_ENUM_PARAMS(4, class T)>
struct tuple;
#define TUPLE_PRINT(z, n, data) data
#define GEN_TUPLE(z, n, unused)                                 \
  template <BOOST_PP_ENUM_PARAMS(n, class T)>                   \
  struct tuple<                                                 \
      BOOST_PP_ENUM_PARAMS(n,T)                                 \
      BOOST_PP_COMMA_IF(n)                                      \
      BOOST_PP_ENUM(                                            \
          BOOST_PP_SUB(4,n), TUPLE_PRINT, none)                 \
  >                                                             \
{                                                               \
    typedef BOOST_PP_ENUM_PARAMS(n, TypeList<T), none           \
    BOOST_PP_REPEAT(n, TUPLE_PRINT, > ) type;                   \
};

ничего злее не видел..срочно удалить smile 

Автор: vinter 16.4.2009, 09:05
Цитата(MAKCim @  16.4.2009,  09:09 Найти цитируемый пост)
поскольку с помощью него можно определять не только константы

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

Цитата(MAKCim @  16.4.2009,  09:09 Найти цитируемый пост)
вы уверены, что глобальные переменные во всех случаях этому не способствуют?

глобальные переменные источник потенциальных ошибок. И лучше взять за правило их не использовать. Кроме того, ГП прививают ненужные зависимости программам. Кстати это я все о С++, на С не писал, не знаю как там дела обстоят.

Цитата(azesmcar @  16.4.2009,  09:15 Найти цитируемый пост)
какой злой код.

зачем городить такой убогий код? typedef'ы нынче не в моде?

Автор: Lazin 16.4.2009, 09:10
Цитата(azesmcar @  16.4.2009,  09:01 Найти цитируемый пост)
ничего злее не видел..срочно удалить

ну, данный код создает 39 специализаций шаблона, вида:

Код

template<class T0, class T1>
struct tuple<T0, T1, none, none...., none>//40 параметров
{
    typedef TypeList<T0, TypeList<T1, none> > type;
};


предлагаешь ручками написать smile 
upd.
если что, я это не писал, а из одного своего проекта скопипастил и немного изменил smile 

Автор: azesmcar 16.4.2009, 09:10
Цитата

зачем городить такой убогий код? typedef'ы нынче не в моде? 

Андрей Александреску когда писал библиотеку Loki видимо не успел изучить typedef. И я тоже видимо не очень хорошо его представляю..не покажете как заменить?

Добавлено через 1 минуту
Цитата

предлагаешь ручками написать 

да шучу я smile спокойствие только спокойствие

Автор: Rickert 16.4.2009, 09:15
Приводить аргументы типа #define size(x) rand() - глупо. Ну и что это такое? Ну define, ну западло и чего дальше-то? Кому это надо такое делать? Уходящему программисту, которому недовыплатили пособие? Так он и без того нагадит smile 

Автор: vinter 16.4.2009, 09:16
с произвольными типами никак, а вот с конкретными легко.

Автор: GoldFinch 16.4.2009, 09:25
Цитата(vinter @  16.4.2009,  10:05 Найти цитируемый пост)
с его помощью еще определяются убогие куски кода, которые нельзя трассировать в дебаге. 

меняйте отладчик, нормальные отладчики трассируют всё

Автор: azesmcar 16.4.2009, 09:26
Цитата

с произвольными типами никак, а вот с конкретными легко.

Так я тоже об этом. Это библиотека, а вот пользователь библиотеки может сделать typedef на конкретные типы и забыть о макросах.
Я только хотел заметить что не все так однозначно. Макросы используются в СТЛ, в БУСТ, в ЛОКИ и во многих других библиотеках написанных серьезными людьми, которые кстати сами советуют избегать макросов. Но это не всегда удается.

Автор: vinter 16.4.2009, 09:36
Цитата(GoldFinch @  16.4.2009,  10:25 Найти цитируемый пост)
меняйте отладчик, нормальные отладчики трассируют всё

не, спасибо, мне в студии удобно и хорошо. Из за макросов менять не собираюсь, я лучше их использовать не буду.

Автор: MAKCim 16.4.2009, 11:04
Цитата(vinter @  16.4.2009,  09:05 Найти цитируемый пост)
Который, между прочим, заменяется inline функциями

inline не всегда inline  smile 

Цитата(vinter @  16.4.2009,  09:05 Найти цитируемый пост)
ага, с его помощью еще определяются убогие куски кода

мысли шире

Код

#define cat(a, b) a##b

Код

#define str(a) #a

и вариации

Цитата(vinter @  16.4.2009,  09:05 Найти цитируемый пост)
глобальные переменные источник потенциальных ошибок

потенциальные ошибки есть всегда

Цитата(vinter @  16.4.2009,  09:05 Найти цитируемый пост)
И лучше взять за правило их не использовать

лучше взять за правило думать прежде чем использовать

Цитата(vinter @  16.4.2009,  09:05 Найти цитируемый пост)
Кроме того, ГП прививают ненужные зависимости программам

static/анонимный namespace отменили?
весь linux построен по принципу 
модуль = *.c файл : {static ГП, static функции, глобальные функции, экспортируемые функции}

Автор: Любитель 16.4.2009, 11:48
MAKCim, C есть С - там свои особенности smile Против них вряд ли кто-то спорить пытается (я надеюсь). Но речь ведь (в первую очередь) про С++? ;)

Автор: azesmcar 16.4.2009, 12:05
Любитель
Ну, макросы необходимы и в С и в С++. Есть по крайней мере 3 (сейчас больше не припоминаю) вещи которые невозможно написать без макросов.
1.
Код

#ifndef HEADER_H
#define HEADER_H
...
#endif

2.
Код

#ifdef DEBUG
#define ASSERT(T) ...
#else
#define ASSERT(T)
#endif

3.
Код

#ifdef WIN32 //windows
create_thread(...)
#else //*nix
pthread_create(...)
#endif

навскидку пока эти 3

Добавлено через 59 секунд
в остальном макросы могут облегчить написание кода, т.е. генерировать то, что надо писать вручную. А тут уже программисту решать, надо или не надо. Зависит от ситуации.

Автор: vinter 16.4.2009, 12:41
azesmcar, я про макросы говорил, а не препроцессор. Препроцессор, бесспорно, вещь нужная.

Цитата(MAKCim @  16.4.2009,  12:04 Найти цитируемый пост)
inline не всегда inline  

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

Цитата(MAKCim @  16.4.2009,  12:04 Найти цитируемый пост)
static/анонимный namespace отменили?

это не глобальные переменные, они глобальны в рамках юнита, а не проекта, разговор не о них(хотя эти тоже лишнее).

Цитата(MAKCim @  16.4.2009,  12:04 Найти цитируемый пост)
весь linux построен по принципу модуль = *.c файл : {static ГП, static функции, глобальные функции, экспортируемые функции}

linux не показатель. Его основа писалась очень давно, времена меняются. Принципы программирования тоже. 

Автор: azesmcar 16.4.2009, 13:15
Цитата

azesmcar, я про макросы говорил, а не препроцессор. Препроцессор, бесспорно, вещь нужная.


Так ведь ASSERT - макрос..и TYPELIST тоже. Речь не о том что надо макросы писать - хорошо и безусловно перед тем как написать макрос стоит хорошенько подумать над другими возможными решениями. Я просто хочу сказать что не стоит так однозначно ставить крест на макросах, иногда без них не обойтись (говоря не обойтись я не имею ввиду что по другому невозможно написать, я имею ввиду что просто другой способ - хуже).

Автор: vinter 16.4.2009, 13:41
azesmcar, ассерт можно на ф-ию заменить, с typelist сложнее, то тоже, я думаю, можно выкрутиться

Автор: azesmcar 16.4.2009, 13:46
Цитата

ассерт можно на ф-ию заменить

можно, но тогда надо будет вручную передавать функции все параметры
и получится вместо
Код

assert( ptr != 0 );

Код

assert(ptr != 0, __FILE__, __LINE__, __FUNCSIG__); //etc...


я уже не говорю о том что #CONDITION в функцию без макросов не передать. Т.е. чтобы асерт выдавал текст проверки.
(типа: assertion failed when checking condition "ptr != 0" in file program.cpp, on line 666, in function myfirstprogram::myfirstfunction)
хотя как я уже написал
Цитата

я не имею ввиду что по другому невозможно написать, я имею ввиду что просто другой способ - хуже


Автор: Lazin 16.4.2009, 13:53
Цитата(vinter @  16.4.2009,  09:36 Найти цитируемый пост)
я лучше их использовать не буду

за сколько часов напишешь без макросов мой пример с предыдущей страницы? smile 

Автор: vinter 16.4.2009, 14:12
Lazin, пока у меня нет необходимости, не будет и ответа. 

Автор: J0ker 16.4.2009, 16:20
1. #pragma once давно уже пора добавить в стандарт:
src/include/blahblahblah.h
src/include/blah/blahblahblah.h

#include "blahblahblah.h"
#include "blah/blahblahblah.h"

2. #define NUM_OF_DUMMIES 32 - зло

3.
#define NUM_OF_DUMMIES 32
.......
#undef NUM_OF_DUMMIES
добро

Автор: azesmcar 16.4.2009, 16:42
И разделил J0ker добро от зла..и воцарился на земле мир и покой, и перестали программисты писать макросы ибо это не кашерно smile 

Откровение от Страуструпа, глава 18, стих 20

Автор: Rickert 17.4.2009, 01:39
Цитата(J0ker @  16.4.2009,  16:20 Найти цитируемый пост)
2. #define NUM_OF_DUMMIES 32 - зло

3.
#define NUM_OF_DUMMIES 32
.......
#undef NUM_OF_DUMMIES
добро 

Объясните мне хоть кто-нибудь: что автор хотел этим сказать?

Автор: Lazin 17.4.2009, 07:54
Цитата(Rickert @  17.4.2009,  01:39 Найти цитируемый пост)
Объясните мне хоть кто-нибудь: что автор хотел этим сказать? 

в данном примере, макроопределение NUM_OF_DUMMIES, действует на небольшую часть исходного кода, только там, где оно нужно

Автор: Rickert 17.4.2009, 12:06
Цитата(Lazin @  17.4.2009,  07:54 Найти цитируемый пост)
в данном примере, макроопределение NUM_OF_DUMMIES, действует на небольшую часть исходного кода, только там, где оно нужно

Вот я и спрашиваю: что автор хотел сказать?

Автор: Любитель 17.4.2009, 16:03
То, что он разрешает использовать макросы, если они не вырываются за пределы файла smile

Автор: nerezus 18.4.2009, 03:48
Не нужны совсем.
В Java/.NET же без них обошлись и кучу гигабайтов успешного кода написали )

Автор: Любитель 18.4.2009, 12:26
Ээ.. Классы тоже не нужны - в С же их нет и без них кучу гигабайтов успешного кода написали ;)
Извини, но это не аргумент smile Это означает, что можно обойтись без них, означает, что можно хорошо обойтись без них. Но никак не означает, что лучше обходится без них.

Автор: Амортизатор2 7.5.2009, 00:24
Глобальные переменные при бесконтрольном их использовании повышают связность кода,  уменьшают гибкость и масштабируемость. Вот это плохой пример их использования:

Код

int a = 0;
...
void foo()
{
//Некоторые вычисления
...
a = some;
}

//Вызов
foo();


Вот тот же пример, сделанный как положено:

Код

int a = 0;

int foo()
{
//Некоторые вычисления
...
return some;
}

//Вызов
a = foo();


Функция foo() - в первом примере грязная, использует деструктивное присваивание переменной a, во втором случае - она чистая, и присваивание делается вне ее, в отдельном грязном коде.

Автор: andrew_121 19.8.2009, 19:23
Цитата(azesmcar @  16.4.2009,  09:10 Найти цитируемый пост)
Андрей Александреску когда писал библиотеку Loki видимо не успел изучить typedef.

Не знаю о какой версии идет речь, но я использую 0.1.17. В ней макросов почти нет. Очень даже удобная вещь. Учитывая что была написана как пример к книге. Даже в некоторых проектах ее встречал.

Автор: 500mhz 26.8.2009, 09:51
Амортизатор2
мистер ну и к чему ваш пример? отдизасмите и найдите 8 отличий )))

вариант 1 будет примерно так
Код


      call foo
      .....
foo:
      //Некоторые вычисления
      mov [varA],eax // если результат вычислений в еах
      ret

varA:
     dd ?



вариант 2 будет примерно так
Код


      call foo
      mov [varA],eax // возврат функции в еах как обычно
      .....
foo:
      //Некоторые вычисления
      ret

varA:
     dd ?





Автор: Любитель 26.8.2009, 12:40
500mhz, а к чему ваш пример? smile Вы сравниваете все решения по бинарному коду?! Т. е. там, например, именовать переменные нормально - тоже не надо?

Автор: 17dufa 26.8.2009, 15:26
не используйте. никогда и нигде.  smile спокойно заменяется Singleton

Автор: Любитель 26.8.2009, 16:20
17dufa, прочитайте недавнюю тему про синглтоны smile 

Автор: nerezus 26.8.2009, 19:14
А Registry?)

Автор: 500mhz 26.8.2009, 20:21
Любитель

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

пс
nerezus шалом бро ) куда пропал?

Автор: nerezus 26.8.2009, 23:45
500mhz, рутина( хата( жена(
Хотя кому как тебе не знать )
Сейчас работаю с PE-файлом на PHP ) Скоро на хабре статья будет ;)
И почему все такие заказы я собираю (((

Автор: Любитель 27.8.2009, 01:06
Цитата(500mhz @  26.8.2009,  20:21 Найти цитируемый пост)
в третьих тема не имеет смысла так как с точки зрения проца , ему фиолетово что глобальные что локальные, на быстродействии не скажеться

Вот и я о том же! И именовать переменные лучше a, b, c, etc. Т. к. во-первых, место на диске (для исходника и объектника) экономим, а к ак следствие - ОЗУ. А итог один...

Цитата(500mhz @  26.8.2009,  20:21 Найти цитируемый пост)
ну во первых то что я привел в качестве примера явно не бинарный код

Но и ещё более явно не исходный. Ассемблерный листинг - это мнемоническое отображение бинарника (игнорируем ассемблерные дефайны, макросы, имена и пр. - не о них то речь!).

Цитата(500mhz @  26.8.2009,  20:21 Найти цитируемый пост)
в четвертых с точки зрения безопасности глобальные безопасней, так как по дефолту они не в стеке, а локальные резервируються (по дефолту) в стеке, так что всегда есть шанс ченить переполнить или запороть

Ну да... Вы писали большие проекты? Безопаснее? Да-да...

А, если серьёзно, тема о другом. Никак не о low-level. smile

Автор: 500mhz 27.8.2009, 16:42
Любитель
для качественного кодинга думаю необходимо понимать как работает компилер и что он выдает на выходе, а потом уже спорить о переменных.

Цитата

Ассемблерный листинг - это мнемоническое отображение бинарника (с) Любитель

однозначно в мемориз )))))  

Автор: nerezus 27.8.2009, 17:11
500mhz, не согласен.

Какая разница, где находится переменная, если спецификация отвечает на вопрос "что произойдет"? Да никакой.
Гораздо важнее, чтобы код был читаемый.

Никому не нужен код, который работает в 5 раз быстрее и занимает 40 строчек вместо 100, если в нем никто не разбирается кроме автора, который может в любой момент покинуть проект.

Главные факторы -  время разрабюотки и поддерживаемость.

Автор: 500mhz 27.8.2009, 17:28
nerezus
ну так и я про то что фиолетово какая переменная локальная или глобальная главное чтоб удобно было

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

Автор: Lazin 27.8.2009, 20:07
Цитата(500mhz @  26.8.2009,  20:21 Найти цитируемый пост)
в третьих тема не имеет смысла так как с точки зрения проца , ему фиолетово что глобальные что локальные, на быстродействии не скажеться
Здесь речь не об архитектуре процессора, а о архитектуре приложения, вам это понятие знакомо?

Цитата(500mhz @  26.8.2009,  20:21 Найти цитируемый пост)
в четвертых с точки зрения безопасности глобальные безопасней, так как по дефолту они не в стеке, а локальные резервируються (по дефолту) в стеке, так что всегда есть шанс ченить переполнить или запороть
правильно написанная программа не портит стек, если она его испортит, то где находятся переменные уже не важно, программа с высокой долей вероятности упадет smile 

Цитата(500mhz @  27.8.2009,  16:42 Найти цитируемый пост)
для качественного кодинга думаю необходимо понимать как работает компилер и что он выдает на выходе, а потом уже спорить о переменных
для качественного кодинга, нужно понимать что такое сайд эффекты и уметь их контролировать smile 

Цитата(500mhz @  27.8.2009,  17:28 Найти цитируемый пост)
вот представь есть у тебя функция в ней локальные переменные, и тут ты вызываеш ну к примеру функцию из внешней dll , а dll ну чуть чуть глюковатая (всякое бывает) и портит стек, кусочек стека где лежат твои переменные (у нас же одно с ней адресное пространство значит и стек один),  возвращаеться твой вызов в твою функцию и бабац результат работы совсем не тот что ожидали

lol smile
а если будут только глобальные переменные, то типа все ОК, да? smile
а как ты напишешь программу, которая будет использовать только глобальные переменные и не будет вызывать ф-ии, если не секрет?

Добавлено @ 20:07
гы гы

Автор: 500mhz 27.8.2009, 21:28
Lazin
ты с темы не соскакивай ))
Цитата

а как ты напишешь программу, которая будет использовать только на глобальные переменные и не будет вызывать ф-ии, если не секрет?

и не путай параметры передаваемые в функцию и переменные , а то как то непрофессионально получаеться у тебя ))))

Автор: Lazin 27.8.2009, 22:22
Цитата(500mhz @  27.8.2009,  21:28 Найти цитируемый пост)
ты с темы не соскакивай ))

а ты вопросы не игнорируй smile 

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

видимо часто доводилось портить...  smile 

...интересно, на меня так подействовало то, что я посмотрел 2 серии Хауса подряд, или я все время так делаю? lol

Автор: 500mhz 27.8.2009, 22:51
Lazin
Ты мой герой и мой кумир ))))

мое скромное имхо что глобальные надежней при дефолтовых настройках компилера
но никто не мешает поставить галочку и передавать все не через стек а через регистры )

Автор: W4FhLF 28.8.2009, 06:07
500mhz, я думал ты мебель продаёшь. smile В ИТ вернулся что ли? 

Автор: 500mhz 28.8.2009, 17:07
W4FhLF
а что тута весь ВХ теперь тусит? ))))

да занят был как бы личной жистью, и вот щас появилось время ))))

пс в тему

полюбому mov eax,1 , быстрее и безрпаснее чем mov eax, [ebp-4]  )))

Автор: nerezus 28.8.2009, 17:33
500mhz, полюбому a = 1 быстрее(для программиста) и безопаснее ;)
По поводу ВХ, то не пречислял себя к нему никогда.

Автор: 500mhz 29.8.2009, 13:06
nerezus
мы тут не про асм vs C  )))

естественно а=1 проще для понимания чем mov eax,1

вопрос в том как а=1 интерпритируеться потом

Автор: Lazin 29.8.2009, 13:16
Цитата(500mhz @  29.8.2009,  13:06 Найти цитируемый пост)
естественно а=1 проще для понимания чем mov eax,1

вопрос в том как а=1 интерпритируеться потом

а оно может интерпретироваться как угодно, в том числе и как expression, а не как statement, и означать оно может вовсе не изменение состояния некоторого участка памяти smile

Добавлено через 46 секунд
ох уж эти asm-онавты... smile 

Автор: nerezus 29.8.2009, 16:30
Цитата

вопрос в том как а=1 интерпритируеться потом
 А у меня нет этого вопроса. Мне пофиг, честное слово.

А вот у тебя будет куча вопросов по переносимости не только между платформами, но и ОС.
Не говоря уже о поддержке.

Если бы мне нужна была 100% прибавка производительности(допустим 100%, хотя в реале эти цифры гораздо меньше и зачастую отрицательные), то я бы рядом поставил вторую железку. Это дешевле, быстрее, проще и удобнее.

Автор: MAKCim 30.8.2009, 10:35
глобальные переменные за _редким_ исключением типа errno (хотя errno на самом деле макрос - вызывающий фкнкцию ;)) должны быть static (С) или в анонимном namespace (C++)
тогда ничего плохого в их использовании нет

Автор: gcc 4.9.2009, 07:29
assessor'ы класса как глобальные переменные можно использовать...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)