Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.192] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 405 406 [407] 408 409 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#6091
,
|
|
|
|
Ну в C++ можно сделать специальный scope-объект, возвращающий переменную в исходное состояние при выходе из scope. Завтра покажу, если интересно.
|
|
Сообщ.
#6092
,
|
|
|
|
Цитата D_KEY @ Ну в C++ можно сделать специальный scope-объект, возвращающий переменную в исходное состояние при выходе из scope. Завтра покажу, если интересно. Ну покажи, если не сложно, только не забывай, что в разных потоках должны быть разные биндинги, т.е. ![]() ![]() #include <iostream> int CONTEXT; void p () { CONTEXT++; } void out () { std::cout << CONTEXT << std::endl; } void a () { with (CONTEXT = 0) { for (i <- 1..1000) { p(); } out(); } } void b () { with (CONTEXT = 0) { for (i <- 1..100) { p(); } out(); } } int main () { thread a(); thread a(); thread b(); wait; return 0; } Что у тебя выведет на печать? Должно ![]() ![]() 100 1000 1000 Не обязательно именно в таком порядке, но именно эти числа. |
|
Сообщ.
#6093
,
|
|
|
|
Что-то вроде такого
![]() ![]() template<typename T> struct StateSaver { StateSaver(T &data) : m_value(data), m_data_ref(data) { } ~StateSaver() { m_data_ref = m_value; } T m_value; T &m_data_ref; }; Ну и соответственно: ![]() ![]() void p_Test () { StateSaver<int> ss(CONTEXT); CONTEXT = 0; p(); std::cout << CONTEXT << std::endl; } Только никакого практического применения не вижу Добавлено Вот с разными потоками придется повозиться... Кстати, а разве в CL локальные биндинги глобальных переменных нормально разруливаются между нитками? |
|
Сообщ.
#6094
,
|
|
|
|
Цитата D_KEY @ Вот с разными потоками придется повозиться... Кстати, а разве в CL локальные биндинги глобальных переменных нормально разруливаются между нитками? Да, потому что это новые биндинги, а не просто установка/восстановление значения. Добавлено Цитата D_KEY @ Что-то вроде такого ... ИМХО, лучше ![]() ![]() template<typename T> struct StateSaver { StateSaver(T &data, T new_value) : m_value(data), m_data_ref(new_value) { } ~StateSaver() { m_data_ref = m_value; } T m_value; T &m_data_ref; }; ![]() ![]() void p_Test () { StateSaver<int> ss(CONTEXT, 0); p(); std::cout << CONTEXT << std::endl; } не? |
|
Сообщ.
#6095
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ Вот с разными потоками придется повозиться... Кстати, а разве в CL локальные биндинги глобальных переменных нормально разруливаются между нитками? Да, потому что это новые биндинги, а не просто установка/восстановление значения. Совсем как там не выйдет. В смысле с обычными глобальными переменными. Нужно писать свою приблуду для создания глобальных переменных и биндингов к ним. Если бы придумалось практическое применение, стоило бы подумать над этим Добавлено Цитата korvin @ не? Можно и так. Суть ты понял - происходит восстановление значение при выходе из текущего scope. Можно еще смарт-поинтер написать для этого Все-равно с нитками это не поможет. И все потому, что скомпилированная версия p уже будет ссылаться на ту самую переменную CONTEXT, что будет видеть при компиляции. |
|
Сообщ.
#6096
,
|
|
|
|
Цитата D_KEY @ Если бы придумалось практическое применение, стоило бы подумать над этим ![]() Любая передача разного рода контекста с возможностью локальной настройки. Не, ну можно конечно все передавать параметрами функций, но это не удобно. Я использовал, когда писал принтер для Паскаля, передавал уровень индентации, т.е. типа ![]() ![]() int INDENT_LEVEL = 0 int INDENT_LENGTH = 2 String indentation () { return makeString( ' ', INDENT_LEVEL * INDENT_LENGTH ) } macro indent (expr) { with (INDENT_LEVEL += INDENT_LENGTH) expr } Block::print () { printBegin() indent { for (expr : body) { expr.print() } } printEnd() } Тут конечно нет многопоточности, хотя можно несколько файлов "параллельно" печатать. Так же можно создавать окружения для функций с сайд эффектами, чтоб потестить их. Добавлено Цитата D_KEY @ Совсем как там не выйдет. В смысле с обычными глобальными переменными. Нужно писать свою приблуду для создания глобальных переменных и биндингов к ним. Если бы придумалось практическое применение, стоило бы подумать над этим Все-равно с нитками это не поможет. И все потому, что скомпилированная версия p уже будет ссылаться на ту самую переменную CONTEXT, что будет видеть при компиляции. Не, это-то мне понятно |
|
Сообщ.
#6097
,
|
|
|
|
Цитата D_KEY @ korvin, а чем ограничивается скоп такой вот "глобальной" копии глобальной переменной? Ну в C++ можно сделать специальный scope-объект, возвращающий переменную в исходное состояние при выходе из scope. |
|
Сообщ.
#6098
,
|
|
|
|
Цитата Qraizer @ Цитата D_KEY @ korvin, а чем ограничивается скоп такой вот "глобальной" копии глобальной переменной?Ну в C++ можно сделать специальный scope-объект, возвращающий переменную в исходное состояние при выходе из scope. scope и ограничивается. То есть даже если мы вернем из scope лямбду, которая по ссылке захватит новый биндинг, то вызов этой лямбды из другого scope приведет к работе с тем биндингом, что будет актуален для scope вызова. По крайней мере так в CL, а задачка, видимо, как раз идет оттуда. В общем в CL все несколько иначе в плане работы с глобальными переменными. Доступ к переменным, видимо, сделан по "именам", а поиск осуществляется в текущем контексте. ![]() ![]() (defvar *my-global* 10) (defun f () (format t "~a~%" *my-global*)) (defun g () (f) (let ((*my-global* 20)) (f)) ![]() ![]() > (g) 10 20 NIL При этом, если определим ![]() ![]() (defun foo () (let ((*my-global* 20)) #'(lambda () (format t "~a~%" *my-global*)))) То результат (funcall (foo)) будет зависеть от значения *my-global* в вызывающем контексте, а привязка к 20 будет "забыта". Добавлено Причем это работает только с глобальными переменными. С обычными let логика примерно такая же, как и в других языках. На всякий случай поясню. format - форматированный вывод, t в данном случае означает стандартный поток вывода, ~a - вывод значения ~% - переход на новую строку(\n в общем). |
|
Сообщ.
#6099
,
|
|
|
|
Цитата korvin @ Еще вопрос знатокам C#: я тут понатыкался на инфу, что обычный цикл for в большинстве случаев (массивы, числовые диапазоны) показывает заметно лучшую производительность, нежели foreach, так ли это и если да, то почему? Конкретно для массивов - гон. Для пользовательских типов - да, такое возможно, foreach будет неявно вызывать GetEnumerator/IEnumerable.Current/MoveNext, есть доп накладные расходы. |
|
Сообщ.
#6100
,
|
|
|
|
Цитата Qraizer @ korvin, а чем ограничивается скоп такой вот "глобальной" копии глобальной переменной? Эм, не знаю как сказать, блоком выполнения, хотя конечно никто не мешает в блоке сохранить ссылку на значение, заданное в новом биндинге, в какую-то еще переменную. Добавлено Цитата D_KEY @ Причем это работает только с глобальными переменными. С обычными let логика примерно такая же, как и в других языках. Глобальность тут не при чем =) ![]() ![]() (defun test () (let ((local 0)) (declare (special local)) (flet ((foo () (format t "~s~%" local))) (foo) (let ((local 1)) (declare (special local)) (foo))))) (test) ![]() ![]() 0 1 |
|
Сообщ.
#6101
,
|
|
|
|
korvin, я говорил об обычном let.
Что такое (declare (special local)) ? Ибо без него все будет так, как говорил я. Добавлено А понял, я использовал не верный термин. Имена с таким поведением называются "специальными", просто глобальные привязки являются такими автоматически. Так? |
|
Сообщ.
#6102
,
|
|
|
|
Цитата D_KEY @ korvin, я говорил об обычном let. Что такое (declare (special local)) ? Ибо без него все будет так, как говорил я. Добавлено А понял, я использовал не верный термин. Имена с таким поведением называются "специальными", просто глобальные привязки являются такими автоматически. Так? Да, специальные переменные. defvar и defparameter объявляют специальные переменные. Qraizer, вспомнил, их скоп ограничевается Динамической областью видимости D_KEY, кстати, в Emacs Lisp нет статического (лексического) скопа, только динамический =) |
|
Сообщ.
#6103
,
|
|
|
|
Вот-вот. Спопы - они такие разные... Сформулируйте сначала для себя, потом для нас.
И всё-таки. Как мне, скажем, синтаксисом C++ ограничить скоп вашего биндинга? Вот где он начинается и где заканчиватся. Чтоб чётко и однозначно: глянул в программу, а там "вот тут один биндинг, а вот тут уже другой; а вон там продолжается первый". |
|
Сообщ.
#6104
,
|
|
|
|
Цитата korvin @ D_KEY, кстати, в Emacs Lisp нет статического (лексического) скопа, только динамический =) Там это как-то пофигу. Правда я и делал-то очень простые вещи. Добавлено Цитата Qraizer @ Вот-вот. Спопы - они такие разные... Сформулируйте сначала для себя, потом для нас. И всё-таки. Как мне, скажем, синтаксисом C++ ограничить скоп вашего биндинга? Вот где он начинается и где заканчиватся. Чтоб чётко и однозначно: глянул в программу, а там "вот тут один биндинг, а вот тут уже другой; а вон там продолжается первый". А из примеров не понятно? Могу перевести их на псевдо-плюсы. Добавлено Если коротко - значение береться из ближайшего по "стэку" scope при вычислении выражения с именем. Добавлено Что-то в таком духе: ![]() ![]() /*defvar*/ my_global = 10; void f() { std::cout << my_global << std::endl; } void g() { f(); { my_global = 20; f(); } } /*...*/ foo() { my_global = 30; return [&]() {std::cout << my_global << std::endl;}; } int main() { g(); auto a = foo(); a(); { my_global = 40; a(); } a(); } ![]() ![]() 10 20 10 40 10 При этом в случае разных ниток установка локальных биндингов не влияет на другие нитки. |
|
Сообщ.
#6105
,
|
|
|
|
Цитата D_KEY @ Нет, не понятно. Не надо переводить на C++, я просил представить в синтаксисе C++ границы этих скопов:А из примеров не понятно? Могу перевести их на псевдо-плюсы. Добавлено Сегодня, 13:11 Если коротко - значение береться из ближайшего по "стэку" scope при вычислении выражения с именем. Добавлено Сегодня, 13:19 Что-то в таком духе: ![]() ![]() int x; void f() { int y = ++x; { int z = ++x; { int t = ++x; } } } |