Здравствуйте, Константин Л., Вы писали:
КЛ>Во всех твоих постах попахивает хамством, фамильярностью и претензией на абсолютную истинность.
Рад что моя личность интересует людей умеющих мыслить так нешаблонно.
КЛ>Ты Г.Саттера читал?
Ой, а если я вместо этого компилятор писал — это не зачтется?
КЛ> Там про разницу м/у постфиксной и префиксной формой написано. И почему в общем случае компилятор первую не может заменить на вторую.
Глубокая мысль! Настолько глубокая, что ты даже видимо не въехал что Саттер хотел сказать.
Собственно почему в общем случае фармы инкремента нельзя заменить понятно и ребенку. Они имеют разную семантику. Вот только она становится одинаковой когда результат выражения не используется, что и происходит в for-е, на базе которого тут решили провести высокоинтеллектуальную дискуссию.
КЛ>Подчеркиваю, что все это относится только к с++. Про с# ничего скзать не могу, хотя, наверное, ситуация мало чем отличается.
Ну, тогда, почембу бы весь этот ... не нести на форуме по С++? Тем самым вы избавити много людей от выслушивания вашей интеллектуальной беседы. И возможно нашли благодарную аудиторию.
КЛ>Просто надо иметь привычку писать ++i вместо i++ если не нужно предыдущее значение. В этом я с тобой согласен.
А я такой глупости не утверждал. Так что не надо меня к ней преплетать! Я предостерег людей от упоительного обсуждения бессмысленных оптимизаций и призвал к выбору формы оператор пользоваться исключительно требованиями алгоритма. Ведь там где нужена инфиксная форма оператора постфиксная не подойдет, и наоборот! Если же значение выражения инкримента не исползуется (как в for-е с классическим паттерном перебора индексов или в случае когда он используется как отдельный statment), то думать как писать пропросту глупо! Тут определяющим фактором может быть, все что угодно (эстетика, соглашения о кодировании, да что угодно) но ни как не соображения производительности.
В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!
ЗЫ
Не прав был все же Вирт и создатели Васика не введя в язык подобных операторов. Ведь холивары лучшее средство привлечения интереса к ЯП.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!
Влад, ты неправ. ++, как и --, в C# перегружать можно, но только один раз — нельзя отдельно перегрузить префиксный и постфиксный вариант, и в этом и есть отличие от C++. Вот тут-то как раз компилятор сделает всё остальное сам.
K>Нет, конечно! У тебя же разные параметры функции. А насчет вычисления инкрементов — да, одинаковый:
Извиняюсь, имелось ввиду вот это
for (int i = 0; i < 10;)
{
Console.WriteLine("{0}", i++);
}
for (int i = 0; i < 10;)
{
Console.WriteLine("{0}", ++i);
}
В данном случае должен быть разный код, так как в одном случае аргумент должен попадать после инкрементации, а во втором до и странно будет, если сгенериться одинаковый код
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Константин Л., Вы писали:
КЛ>>Во всех твоих постах попахивает хамством, фамильярностью и претензией на абсолютную истинность.
VD>Рад что моя личность интересует людей умеющих мыслить так нешаблонно.
КЛ>>Ты Г.Саттера читал?
VD>Ой, а если я вместо этого компилятор писал — это не зачтется?
покажешь?
КЛ>> Там про разницу м/у постфиксной и префиксной формой написано. И почему в общем случае компилятор первую не может заменить на вторую.
VD>Глубокая мысль! Настолько глубокая, что ты даже видимо не въехал что Саттер хотел сказать. VD>Собственно почему в общем случае фармы инкремента нельзя заменить понятно и ребенку. Они имеют разную семантику. Вот только она становится одинаковой когда результат выражения не используется, что и происходит в for-е, на базе которого тут решили провести высокоинтеллектуальную дискуссию.
Разумно
КЛ>>Подчеркиваю, что все это относится только к с++. Про с# ничего скзать не могу, хотя, наверное, ситуация мало чем отличается.
VD>Ну, тогда, почембу бы весь этот ... не нести на форуме по С++? Тем самым вы избавити много людей от выслушивания вашей интеллектуальной беседы. И возможно нашли благодарную аудиторию.
Не тебе решать, что и где мне "нести". Хорошь хамить
КЛ>>Просто надо иметь привычку писать ++i вместо i++ если не нужно предыдущее значение. В этом я с тобой согласен.
VD>А я такой глупости не утверждал. Так что не надо меня к ней преплетать! Я предостерег людей от упоительного обсуждения бессмысленных оптимизаций и призвал к выбору формы оператор пользоваться исключительно требованиями алгоритма. Ведь там где нужена инфиксная форма оператора постфиксная не подойдет, и наоборот! Если же значение выражения инкримента не исползуется (как в for-е с классическим паттерном перебора индексов или в случае когда он используется как отдельный statment), то думать как писать пропросту глупо! Тут определяющим фактором может быть, все что угодно (эстетика, соглашения о кодировании, да что угодно) но ни как не соображения производительности.
Опять повторяю — постфиксная форма делает копию объекта. То, что современные компиляторы могут превращать i++ в ++i это уже другое дело.
VD>В C# (и вроде бы в MC++) кстати, нельзя перегружить оператор "++". В нем можено перегрузить оператор "+". При этом компилятор встретив "++" заменит его на соотвествющую комбинацию сложения и присвоения. Но это так же никак не должно влиять на выбор варианта операции!
их перегружать можно
VD>ЗЫ
VD>Не прав был все же Вирт и создатели Васика не введя в язык подобных операторов. Ведь холивары лучшее средство привлечения интереса к ЯП.
Здравствуйте, Константин Л., Вы писали:
КЛ>Вижу, что человек в предмете не разбирается...
Я, честно говоря, тоже в предмете не разбираюсь. Потому считаю, что такие вещи, как отслеживание использования результатов операции, должен делать компилятор.
С моей точки зрения, подобные хитрости сродни переставлению веток в if/else так, чтобы первой шла та, у которой выше вероятность (тут с год назад один к.ф.-м.н. на полном серъезе это приводил как безусловную рекомендацию). А может, еще пообсуждаем влияние длины имен переменных на скорость компиляции? 21 век на дворе. Скоро будем праздновать столетие машины Тьюринга, а тут такие тонкости.
Нет, я не спорю. Под DSP наверняка компиляторы до сих пор оптимизируют так позорно, что и от порядка аргументов в операторе + скорость может зависеть. Но общая рекомендация должна быть ровно такая, как привел Влад — не заморачивайтесь ерундой без веской причины!
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Oyster, Вы писали:
O>Влад, ты неправ. ++, как и --, в C# перегружать можно, но только один раз — нельзя отдельно перегрузить префиксный и постфиксный вариант, и в этом и есть отличие от C++. Вот тут-то как раз компилятор сделает всё остальное сам.
Впрочем, это несущественное исправление, не влияющее на суть ответа.
Здравствуйте, Ведмедь, Вы писали:
В>Здравствуйте, kpumuk, Вы писали:
K>>Нет, конечно! У тебя же разные параметры функции. А насчет вычисления инкрементов — да, одинаковый:
В>Извиняюсь, имелось ввиду вот это В>
В>for (int i = 0; i < 10;)
В>{
В> Console.WriteLine("{0}", i++);
В>}
В>for (int i = 0; i < 10;)
В>{
В> Console.WriteLine("{0}", ++i);
В>}
В>
В>В данном случае должен быть разный код, так как в одном случае аргумент должен попадать после инкрементации, а во втором до и странно будет, если сгенериться одинаковый код
Здравствуйте, Ведмедь, Вы писали:
В>Здравствуйте, kpumuk, Вы писали:
K>>Нет, конечно! У тебя же разные параметры функции. А насчет вычисления инкрементов — да, одинаковый:
В>Извиняюсь, имелось ввиду вот это В>
В>for (int i = 0; i < 10;)
В>{
В> Console.WriteLine("{0}", i++);
В>}
В>for (int i = 0; i < 10;)
В>{
В> Console.WriteLine("{0}", ++i);
В>}
В>
В>В данном случае должен быть разный код, так как в одном случае аргумент должен попадать после инкрементации, а во втором до и странно будет, если сгенериться одинаковый код
Я тебе привел IL-код именно для этого примера. Как видишь, разница только в месторасположении инструкции dup.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Константин Л., Вы писали:
КЛ>>Вижу, что человек в предмете не разбирается... S>Я, честно говоря, тоже в предмете не разбираюсь. Потому считаю, что такие вещи, как отслеживание использования результатов операции, должен делать компилятор. S>С моей точки зрения, подобные хитрости сродни переставлению веток в if/else так, чтобы первой шла та, у которой выше вероятность (тут с год назад один к.ф.-м.н. на полном серъезе это приводил как безусловную рекомендацию). А может, еще пообсуждаем влияние длины имен переменных на скорость компиляции? 21 век на дворе. Скоро будем праздновать столетие машины Тьюринга, а тут такие тонкости. S>Нет, я не спорю. Под DSP наверняка компиляторы до сих пор оптимизируют так позорно, что и от порядка аргументов в операторе + скорость может зависеть. Но общая рекомендация должна быть ровно такая, как привел Влад — не заморачивайтесь ерундой без веской причины!
Здравствуйте, 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;
}
}
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, kpumuk, Вы писали:
K>>Более того, оператор ++ нельзя перегрузить для инстанса, только для типа (static). Следовательно, хоть префиксная форма, хоть постфиксная — происходит создание нового экземпляра объекта. Вывод прост — как ни крути, а время выполнения будет одинаковым
А>может я чего-то недопонимаю А>но где здесь создастся новый экземпляр?
Ого, ни фига себе я выдал. Все-так болеть и думать — вещи несовместимые...
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, 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
В общем хоть прошлое сообщение было бредом, выводы были правильные — разницы никакой
Здравствуйте, Константин Л., Вы писали:
КЛ>Опять повторяю — постфиксная форма делает копию объекта. То, что современные компиляторы могут превращать i++ в ++i это уже другое дело.
Но мы ведь находимся в ветке .NET. Разве JIT — не современный компилятор? И копию он делает и для префиксной, и для постфиксной формы (конечно, если это value-type и результат используется в выражении), разница только в том, делает это он до или после инкремента. Такова специфика стековой архитектуры...
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