Если это ваш первый визит, рекомендуем почитать справку по форуму. Для размещения своих сообщений необходимо зарегистрироваться. Для просмотра сообщений выберите раздел. |
Инкременты |
Философия, технологии, алгоритмы! |
|
Опции темы |
23.01.2004, 15:10 | #1 |
Форумец
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39
Не в сети |
Инкременты
Как то уважаемый is посоветывал использовать префиксный
инкремент: лучше использовать его, чем постфиксный. Т.е. в циклах вместо y++ записать ++y. Решил проверить чем же лучше, и для двух процедур: Код:
static void Postfix() { for(int i = 0; i < 10; i++) { Console.WriteLine(i); } } static void Prefix() { for(int i = 0; i < 10; ++i) { Console.WriteLine(i); } } Код:
.method private hidebysig static void Prefix() cil managed { .maxstack 2 .locals init (int32 V_0) IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_000e IL_0004: ldloc.0 IL_0005: call void [mscorlib]System.Console::WriteLine(int32) IL_000a: ldloc.0 IL_000b: ldc.i4.1 IL_000c: add IL_000d: stloc.0 IL_000e: ldloc.0 IL_000f: ldc.i4.s 10 IL_0011: blt.s IL_0004 IL_0013: ret } ухищрения не подходят для нового языка. Может быть различие инкриментов проявляется в другом случае ? Кстати где про это можно почитать в сети ? LSL добавил [date]1074864980[/date]: PS: Для полноты картины ещё и одинаковый код времени выполнения: Код:
0000000f jmp 00000018 00000011 call dword ptr ds:[79C29078h] // Вызывается метод. 00000017 inc esi 00000018 cmp esi,0Ah 0000001b jl 00000011 |
23.01.2004, 16:44 | #2 | ||
парадоксов друг...
Сообщений: 286
Регистрация: 31.08.2003
Не в сети |
Re: Инкременты
Цитата:
В таких простых случаях без разницы как использовать. А вот когда надо будет получить результат выражения... Цитата:
int j=++i; i=0; int k=i++; if (j != k) { throw ("Тады ой!"); } Неужто не знал? |
||
23.01.2004, 17:42 | #4 |
Форумец
Сообщений: 334
Регистрация: 14.04.2003
Возраст: 42
Не в сети |
Совет очень даже верен для итераторов.
|
23.01.2004, 19:46 | #5 |
Форумец
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39
Не в сети |
RomanPshenichny этот совет оказался бессмысленным для моего случая, когда я использовал итератор в цикле, дизассемблированный код оказался одинаков и для префиксной и для постфиксной записи.
Я хочу понять это особенность Си шарпа или у меня частный случай, когда нет разницы. |
24.01.2004, 12:38 | #6 | |
парадоксов друг...
Сообщений: 286
Регистрация: 31.08.2003
Не в сети |
Цитата:
Код:
class X { private: void some_action(){}; public: operator ++() // префикс { some_action(); return *this; } operator ++(int) // постфикс { X temp=*this; some_action(); return temp; } }; И если ты немного подумаешь, то сможешь понять, что в диезе будет то же самое. При этом учти, что компилятор всё это наверняка соптимизирует... |
|
24.01.2004, 13:41 | #7 |
Форумец
Сообщений: 111
Регистрация: 04.02.2003
Не в сети |
Ух ты, тут вовсю обсуждение моих советов идет, а я и не в курсе :)
LSL Вот смотри как это дело в отношении префиксной и постфиксной форме обстоит в стандарте С++ ======================================== [expr.post.incr] 5.2.6 Increment and decrement 1 The value obtained by applying a postfix ++ is the value that the operand had before applying the operator. [Note: the value obtained is a copy of the original value ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a complete object type. After the result is noted, the value of the object is modified by adding 1 to it, unless the object is of type bool, in which case it is set to true. [Note: this use is deprecated, see annex D. ] The result is an rvalue. The type of the result is the cvunqualified version of the type of the operand. See also 5.7 and 5.17. __________________ [expr.pre.incr] 5.3.2 Increment and decrement 1 The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated). The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a completelydefined object type. The value is the new value of the operand; it is an lvalue. If x is not of type bool, the expression ++x is equivalent to x+=1. [Note: see the discussions of addition (5.7) and assignment operators (5.17) for information on conversions. ] ============================================ Я там вторые подпункты относительно декремента. В них говорится, что в случае декремента аналогично :) Идем далее :) Реализация постфиксного инкремента обычно менее эффективно, чем префиксного. Постфиксный инкремент может выглядеть так const T T::operator++(int) { T tmp(*this); ++*this; return tmp; } Либо для более четкого понимания: для префиксной формы y =++x; аналогично y=(x+=1); Значением y будет новое значение. Для постфиксной формы: y=x++; аналогично y=(t=x,x+=1,t). [Прим. is - запятая в С++ устанавливает точки следования] Значением y будет старое значение x Так вот к чему я веду? ;) Если старое значение не нужно (насколько я понял в твоём случае это именно так), то использование префиксной формы более предпочтительно. Т.е. just keep in mind :) Но это для плюсов, для шарпа, возможно, дело обстоит иначе - пока еще до него руки не дошли :( |
25.01.2004, 14:27 | #8 |
Форумец
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39
Не в сети |
is Для шарпа так же.
Postfix 1)x is evaluated to produce the variable. 2)The value of x is saved. 3)The selected operator is invoked with the saved value of x as its argument. 4)The value returned by the operator is stored in the location given by the evaluation of x. 5)The saved value of x becomes the result of the operation. Prefix 1)x is evaluated to produce the variable. 2)The selected operator is invoked with the value of x as its argument. 3)The value returned by the operator is stored in the location given by the evaluation of x. 4)The value returned by the operator becomes the result of the operation. И всё же, в цикле нет разницы какой инкремент использовать.. |
11.02.2004, 17:40 | #10 |
Gross
|
Постфиксный инкремент отличается от префиксного тем, что возвращает не инкрементированное значение, а исходное.
Правило эффективного использования инкрементов формулируется просто: если вам не нужно исходное значение после увеличения, используйте префиксную форму оператора. Бессмысленное использование постфисной формы приводит к непроизвольному созданию временных объектов, которые порою могут быть очень большими. В случае, описанном LSL имеет место инкремент встроенного типа int. Для таких простых типов (int, complex, char и пр.) компилятор оказывается способным оптимизировать код благодоря замене постфиксной формы на префиксную. Так что не стоит строить особенных иллюзий на счет C#, этот язык не слишком отличается от C++, хотя и является менее мощным но более объектно-ориентированным. |
11.02.2004, 20:23 | #11 |
Форумец
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39
Не в сети |
Grossmeister
О всевидящие, за что мне такое наказание Я же привёл пример и на ассемблере и на "независимом языке"! Что может быть ещё очивиднее ? Факт: в C# в цикле нет разницы какой инкримент использовать. (Возможно у меня частный случай.) Неужели, я в который раз так недоступно объясняю ? По поводу сходства с си: Классы и структуры в c# принципиально отличаются от объектов и структур в Си++. Обьект в си шарпе это структура данных которая хранится в управляемой куче (managed heap) Структура - тип данных который хранится в стеке потока домена. Структура является размерным типом, объект - ссылочный. И вообще это тонкий и серъёзный вопрос, над которым рассуждать не вижу смысла. Если не ошибаюсь структура и класс в Си++ одно и то же, различие в области видимости.......... |
12.02.2004, 19:12 | #12 |
Gross
|
LSL Ты читал что я написал? Для таких простых типов (int, complex, char и пр.) компилятор оказывается способным оптимизировать код благодоря замене постфиксной формы на префиксную. Попробуй инкрементировать итератор.
Grossmeister добавил [date]1076606285[/date]: И C# в смысле автоматического управления памятью (подобно Java) пока сомнительно (по эффективности) себя ведет. |
12.02.2004, 23:08 | #13 |
Форумец
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39
Не в сети |
Grossmeister
Ты читал что я написал? Это я к тому твоему выссказыванию: "C#, этот язык не слишком отличается от C++" Для таких простых типов (int, complex, char и пр.) компилятор оказывается способным оптимизировать код благодоря замене постфиксной формы на префиксную Скорее всего. Попробуй инкрементировать итератор. А я что делал ? И C# в смысле автоматического управления памятью (подобно Java) пока сомнительно (по эффективности) себя ведет. В чём же сомнения если не сектрет? |
12.02.2004, 23:20 | #14 | ||
Gross
|
LSL
Цитата:
Цитата:
|
||
13.02.2004, 00:42 | #15 |
Форумец
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39
Не в сети |
Grossmeister
Боюсь что в некоторых случаях (например, резкое наращивание и урезание контейнерных объектов) будет сильно тормозить Что такое контейнерные объекты ? Я с большой увереностью заявляю что при создании и уничтожении объектов никаких тормозов нет и не будет. на нем точно писать не будут, разве что простенькие клиентские приложения (мультиплатформенную клиентскую логику). .net, ado.net - отличный выбор для бд. Это факт. Только что играл в Quake 2 переписанный под .net, www.vertigosoftware.com. Одним слово - круто Так что ты там говорил про тормоза ? |