Re[12]: i++ VS ++i
От: VladD2 Российская Империя www.nemerle.org
Дата: 11.05.06 20:21
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Во всех твоих постах попахивает хамством, фамильярностью и претензией на абсолютную истинность.


Рад что моя личность интересует людей умеющих мыслить так нешаблонно.

КЛ>Ты Г.Саттера читал?


Ой, а если я вместо этого компилятор писал — это не зачтется?

КЛ> Там про разницу м/у постфиксной и префиксной формой написано. И почему в общем случае компилятор первую не может заменить на вторую.


Глубокая мысль! Настолько глубокая, что ты даже видимо не въехал что Саттер хотел сказать.
Собственно почему в общем случае фармы инкремента нельзя заменить понятно и ребенку. Они имеют разную семантику. Вот только она становится одинаковой когда результат выражения не используется, что и происходит в for-е, на базе которого тут решили провести высокоинтеллектуальную дискуссию.

КЛ>Подчеркиваю, что все это относится только к с++. Про с# ничего скзать не могу, хотя, наверное, ситуация мало чем отличается.


Ну, тогда, почембу бы весь этот ... не нести на форуме по С++? Тем самым вы избавити много людей от выслушивания вашей интеллектуальной беседы. И возможно нашли благодарную аудиторию.

КЛ>Просто надо иметь привычку писать ++i вместо i++ если не нужно предыдущее значение. В этом я с тобой согласен.


А я такой глупости не утверждал. Так что не надо меня к ней преплетать! Я предостерег людей от упоительного обсуждения бессмысленных оптимизаций и призвал к выбору формы оператор пользоваться исключительно требованиями алгоритма. Ведь там где нужена инфиксная форма оператора постфиксная не подойдет, и наоборот! Если же значение выражения инкримента не исползуется (как в for-е с классическим паттерном перебора индексов или в случае когда он используется как отдельный statment), то думать как писать пропросту глупо! Тут определяющим фактором может быть, все что угодно (эстетика, соглашения о кодировании, да что угодно) но ни как не соображения производительности.

В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!

ЗЫ

Не прав был все же Вирт и создатели Васика не введя в язык подобных операторов. Ведь холивары лучшее средство привлечения интереса к ЯП.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: i++ VS ++i
От: Oyster Украина https://github.com/devoyster
Дата: 12.05.06 06:26
Оценка: +3
Здравствуйте, VladD2, Вы писали:

VD>В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!


Влад, ты неправ. ++, как и --, в C# перегружать можно, но только один раз — нельзя отдельно перегрузить префиксный и постфиксный вариант, и в этом и есть отличие от C++. Вот тут-то как раз компилятор сделает всё остальное сам.
Re[4]: i++ VS ++i
От: Ведмедь Россия  
Дата: 12.05.06 07:16
Оценка:
Здравствуйте, kpumuk, Вы писали:



K>Нет, конечно! У тебя же разные параметры функции. А насчет вычисления инкрементов — да, одинаковый:


Извиняюсь, имелось ввиду вот это
for (int i = 0; i < 10;)
{
 Console.WriteLine("{0}", i++);
}

for (int i = 0; i < 10;)
{
  Console.WriteLine("{0}", ++i);
}


В данном случае должен быть разный код, так как в одном случае аргумент должен попадать после инкрементации, а во втором до и странно будет, если сгенериться одинаковый код
Да пребудет с тобой Великий Джа
Re[13]: i++ VS ++i
От: Константин Л. Франция  
Дата: 12.05.06 08:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Константин Л., Вы писали:


КЛ>>Во всех твоих постах попахивает хамством, фамильярностью и претензией на абсолютную истинность.


VD>Рад что моя личность интересует людей умеющих мыслить так нешаблонно.


КЛ>>Ты Г.Саттера читал?


VD>Ой, а если я вместо этого компилятор писал — это не зачтется?


покажешь?

КЛ>> Там про разницу м/у постфиксной и префиксной формой написано. И почему в общем случае компилятор первую не может заменить на вторую.


VD>Глубокая мысль! Настолько глубокая, что ты даже видимо не въехал что Саттер хотел сказать.

VD>Собственно почему в общем случае фармы инкремента нельзя заменить понятно и ребенку. Они имеют разную семантику. Вот только она становится одинаковой когда результат выражения не используется, что и происходит в for-е, на базе которого тут решили провести высокоинтеллектуальную дискуссию.

Разумно

КЛ>>Подчеркиваю, что все это относится только к с++. Про с# ничего скзать не могу, хотя, наверное, ситуация мало чем отличается.


VD>Ну, тогда, почембу бы весь этот ... не нести на форуме по С++? Тем самым вы избавити много людей от выслушивания вашей интеллектуальной беседы. И возможно нашли благодарную аудиторию.


Не тебе решать, что и где мне "нести". Хорошь хамить

КЛ>>Просто надо иметь привычку писать ++i вместо i++ если не нужно предыдущее значение. В этом я с тобой согласен.


VD>А я такой глупости не утверждал. Так что не надо меня к ней преплетать! Я предостерег людей от упоительного обсуждения бессмысленных оптимизаций и призвал к выбору формы оператор пользоваться исключительно требованиями алгоритма. Ведь там где нужена инфиксная форма оператора постфиксная не подойдет, и наоборот! Если же значение выражения инкримента не исползуется (как в for-е с классическим паттерном перебора индексов или в случае когда он используется как отдельный statment), то думать как писать пропросту глупо! Тут определяющим фактором может быть, все что угодно (эстетика, соглашения о кодировании, да что угодно) но ни как не соображения производительности.


Опять повторяю — постфиксная форма делает копию объекта. То, что современные компиляторы могут превращать i++ в ++i это уже другое дело.

VD>В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!


их перегружать можно

VD>ЗЫ


VD>Не прав был все же Вирт и создатели Васика не введя в язык подобных операторов. Ведь холивары лучшее средство привлечения интереса к ЯП.


холивары тут не помогут
Re[10]: i++ VS ++i
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.05.06 09:20
Оценка: +4
Здравствуйте, Константин Л., Вы писали:

КЛ>Вижу, что человек в предмете не разбирается...

Я, честно говоря, тоже в предмете не разбираюсь. Потому считаю, что такие вещи, как отслеживание использования результатов операции, должен делать компилятор.
С моей точки зрения, подобные хитрости сродни переставлению веток в if/else так, чтобы первой шла та, у которой выше вероятность (тут с год назад один к.ф.-м.н. на полном серъезе это приводил как безусловную рекомендацию). А может, еще пообсуждаем влияние длины имен переменных на скорость компиляции? 21 век на дворе. Скоро будем праздновать столетие машины Тьюринга, а тут такие тонкости.
Нет, я не спорю. Под DSP наверняка компиляторы до сих пор оптимизируют так позорно, что и от порядка аргументов в операторе + скорость может зависеть. Но общая рекомендация должна быть ровно такая, как привел Влад — не заморачивайтесь ерундой без веской причины!
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: i++ VS ++i
От: Oyster Украина https://github.com/devoyster
Дата: 12.05.06 09:24
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Влад, ты неправ. ++, как и --, в C# перегружать можно, но только один раз — нельзя отдельно перегрузить префиксный и постфиксный вариант, и в этом и есть отличие от C++. Вот тут-то как раз компилятор сделает всё остальное сам.


Впрочем, это несущественное исправление, не влияющее на суть ответа.
Re[5]: i++ VS ++i
От: krasin Россия  
Дата: 12.05.06 09:39
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>Здравствуйте, kpumuk, Вы писали:




K>>Нет, конечно! У тебя же разные параметры функции. А насчет вычисления инкрементов — да, одинаковый:


В>Извиняюсь, имелось ввиду вот это

В>
В>for (int i = 0; i < 10;)
В>{
В> Console.WriteLine("{0}", i++);
В>}

В>for (int i = 0; i < 10;)
В>{
В>  Console.WriteLine("{0}", ++i);
В>}
В>


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


.method private hidebysig static void Main() cil managed
{
      .entrypoint
      .maxstack 4
      .locals init (
            int32 num1,
            int32 num2)
      L_0000: ldc.i4.0 
      L_0001: stloc.0 
      L_0002: br.s L_0018
      L_0004: ldstr "{0}"
      L_0009: ldloc.0 
      L_000a: dup 
      L_000b: ldc.i4.1 
      L_000c: add 
      L_000d: stloc.0 
      L_000e: box int32
      L_0013: call void [mscorlib]System.Console::WriteLine(string, object)
      L_0018: ldloc.0 
      L_0019: ldc.i4.s 10
      L_001b: blt.s L_0004

      L_001d: ldc.i4.0 
      L_001e: stloc.1 
      L_001f: br.s L_0035
      L_0021: ldstr "{0}"
      L_0026: ldloc.1 
      L_0027: ldc.i4.1 
      L_0028: add 
      L_0029: dup 
      L_002a: stloc.1 
      L_002b: box int32
      L_0030: call void [mscorlib]System.Console::WriteLine(string, object)
      L_0035: ldloc.1 
      L_0036: ldc.i4.s 10
      L_0038: blt.s L_0021

      L_003a: ret 
}

Код, конечно, разный. Только вот работает он за одинаковое время, очевидно.
Re[5]: i++ VS ++i
От: kpumuk Украина http://kpumuk.info/
Дата: 12.05.06 09:39
Оценка:
Здравствуйте, Ведмедь, Вы писали:

В>Здравствуйте, kpumuk, Вы писали:




K>>Нет, конечно! У тебя же разные параметры функции. А насчет вычисления инкрементов — да, одинаковый:


В>Извиняюсь, имелось ввиду вот это

В>
В>for (int i = 0; i < 10;)
В>{
В> Console.WriteLine("{0}", i++);
В>}

В>for (int i = 0; i < 10;)
В>{
В>  Console.WriteLine("{0}", ++i);
В>}
В>


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


Я тебе привел IL-код именно для этого примера. Как видишь, разница только в месторасположении инструкции dup.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[11]: i++ VS ++i
От: Константин Л. Франция  
Дата: 12.05.06 09:44
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Константин Л., Вы писали:


КЛ>>Вижу, что человек в предмете не разбирается...

S>Я, честно говоря, тоже в предмете не разбираюсь. Потому считаю, что такие вещи, как отслеживание использования результатов операции, должен делать компилятор.
S>С моей точки зрения, подобные хитрости сродни переставлению веток в if/else так, чтобы первой шла та, у которой выше вероятность (тут с год назад один к.ф.-м.н. на полном серъезе это приводил как безусловную рекомендацию). А может, еще пообсуждаем влияние длины имен переменных на скорость компиляции? 21 век на дворе. Скоро будем праздновать столетие машины Тьюринга, а тут такие тонкости.
S>Нет, я не спорю. Под DSP наверняка компиляторы до сих пор оптимизируют так позорно, что и от порядка аргументов в операторе + скорость может зависеть. Но общая рекомендация должна быть ровно такая, как привел Влад — не заморачивайтесь ерундой без веской причины!

Да никто и не заморачивается
Re[14]: i++ VS ++i
От: kpumuk Украина http://kpumuk.info/
Дата: 12.05.06 09:50
Оценка: -2
Здравствуйте, Oyster, Вы писали:

O>Здравствуйте, VladD2, Вы писали:


VD>>В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!


O>Влад, ты неправ. ++, как и --, в C# перегружать можно, но только один раз — нельзя отдельно перегрузить префиксный и постфиксный вариант, и в этом и есть отличие от C++. Вот тут-то как раз компилятор сделает всё остальное сам.


Более того, оператор ++ нельзя перегрузить для инстанса, только для типа (static). Следовательно, хоть префиксная форма, хоть постфиксная — происходит создание нового экземпляра объекта. Вывод прост — как ни крути, а время выполнения будет одинаковым
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: i++ VS ++i
От: Аноним  
Дата: 12.05.06 10:11
Оценка:
Здравствуйте, kpumuk, Вы писали:


K>Более того, оператор ++ нельзя перегрузить для инстанса, только для типа (static). Следовательно, хоть префиксная форма, хоть постфиксная — происходит создание нового экземпляра объекта. Вывод прост — как ни крути, а время выполнения будет одинаковым


может я чего-то недопонимаю
но где здесь создастся новый экземпляр?


class A
{
    private int n = 0;

    public static A operator ++(A a)
    {
        a.n++;
        return a;
    }
}
Re[16]: i++ VS ++i
От: kpumuk Украина http://kpumuk.info/
Дата: 12.05.06 10:25
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, kpumuk, Вы писали:



K>>Более того, оператор ++ нельзя перегрузить для инстанса, только для типа (static). Следовательно, хоть префиксная форма, хоть постфиксная — происходит создание нового экземпляра объекта. Вывод прост — как ни крути, а время выполнения будет одинаковым


А>может я чего-то недопонимаю

А>но где здесь создастся новый экземпляр?

Ого, ни фига себе я выдал. Все-так болеть и думать — вещи несовместимые...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[16]: i++ VS ++i
От: kpumuk Украина http://kpumuk.info/
Дата: 12.05.06 10:39
Оценка: 4 (1)
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, kpumuk, Вы писали:



K>>Более того, оператор ++ нельзя перегрузить для инстанса, только для типа (static). Следовательно, хоть префиксная форма, хоть постфиксная — происходит создание нового экземпляра объекта. Вывод прост — как ни крути, а время выполнения будет одинаковым


А>может я чего-то недопонимаю

А>но где здесь создастся новый экземпляр?

Я вроде понял, что имел в виду в предыдущем сообщении.
Если использовать ++ для reference-типов, и в этом операторе изменять внутреннее состояние объекта, префиксная форма или постфиксная — не имеет значения. Почему?
Вот:

class Program
{
        static void Main(string[] args)
        {
                int h = 0;
                A x;
                
                x = new A(0);
                h = ++x + 1;
                Console.WriteLine("++x + 1: {0}", h);

                x = new A(0);
                h = x++ + 1;
                Console.WriteLine("x++ + 1: {0}", h);

                Console.ReadLine();
        }
}

class A
{
        private int n;
        
        public A(int n)
        {
                this.n = n;
        }

        public static A operator ++(A a)
        {
                a.n++;
                return a;
        }
        
        public static implicit operator int(A a)
        {
                return a.n;
        }
}


Результат:
++x + 1: 2
x++ + 1: 2


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

А вот для value-типов все нормально, dup копирует объект в обоих случаях. Стоит заменить class на struct и получаем:
++x + 1: 2
x++ + 1: 1


В общем хоть прошлое сообщение было бредом, выводы были правильные — разницы никакой
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[14]: i++ VS ++i
От: kpumuk Украина http://kpumuk.info/
Дата: 12.05.06 16:45
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Опять повторяю — постфиксная форма делает копию объекта. То, что современные компиляторы могут превращать i++ в ++i это уже другое дело.


Но мы ведь находимся в ветке .NET. Разве JIT — не современный компилятор? И копию он делает и для префиксной, и для постфиксной формы (конечно, если это value-type и результат используется в выражении), разница только в том, делает это он до или после инкремента. Такова специфика стековой архитектуры...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[14]: i++ VS ++i
От: gear nuke  
Дата: 16.05.06 04:17
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Опять повторяю — постфиксная форма делает копию объекта.


Действительно.
Рассмотрим типичный итератор:
iterator operator++(int) { iterator tmp( *this ); ++*this; return tmp; }

Теперь использование:
iterator i;

// копия используется, компилятор сделает: 
// iterator j( i ); ++i;
iterator j = i++;

// копия не используется, стало быть компилятор не будет её создавать.
i++;

КЛ>То, что современные компиляторы могут превращать i++ в ++i это уже другое дело

Это не заслуга компилятора — мы сами так написали в определении, компилятор лишь выкинул неиспользуемые переменные.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.