Почему в С++ можно ставить плюсы перед ++С...
От: Ароан Россия  
Дата: 14.07.06 14:39
Оценка: +1 :)))
Объясните почему на C++ работает следующая конструкция:

(++С)++


А вот такая не работает:

++(С++)


Можно подумать что постфиксный ++ не требует l-value, но такие конструкции тоже не работают:

++(С+1)
(С+1)++


P.S. В C# этой фичи нет.
Re[3]: Почему в С++ можно ставить плюсы перед ++С...
От: Dmitry Kotlyarov Россия  
Дата: 14.07.06 15:49
Оценка: 1 (1) +1
Здравствуйте, Ароан, Вы писали:

А>Но возникает другой вопрос, зачем все это надо?

А>Есть ли какая-то разумная причина возвращать l-value?

Конечно. Использование префиксного инкремента позволяет избежать создания временного объекта.

// Тут компилятор может оптимизировать код, заменив постфиксный инкремент на префиксный.
for (int i=0; i<10; i++) {}

class A
{/*...*/};

// А вот тут компилятор не имеет права выполнить оптимизацию, т.к. a++ может иметь побочный эффект.
// Кроме того, префиксная форма ++ для пользовательского типа может не отвечать принятой семантике.
// Поэтому убедиться в законности такой замены не под силу большинству компиляторов (если не всем).
for (A a=/*...*/; /*...*/; a++) {}
Re[4]: Почему в С++ можно ставить плюсы перед ++С...
От: Павел Кузнецов  
Дата: 15.07.06 00:55
Оценка: +2
Здравствуйте, Кодт, Вы писали:

А>>Есть ли какая-то разумная причина возвращать l-value?


К>Да: двойной автоинкремент. ++ ++ x


UB
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Почему в С++ можно ставить плюсы перед ++С...
От: shank  
Дата: 14.07.06 14:59
Оценка: 1 (1)
Здравствуйте, Ароан, Вы писали:

А>Объясните почему на C++ работает следующая конструкция:

Оба постфиксный и префиксный ++ должны применяться к lvalue (для встроенных типов). НО: Префиксный оператор инкремента возвращает lvalue, а постфиксный — rvalue.

А>
А>(++С)++ // преинкремент возвращает lvalue, поэтому к нему можно применять постинкремент
А>


А>А вот такая не работает:


А>
А>++(С++) // постинкремент возвращает rvalue, поэтому преинкремент обламывается
А>


А>Можно подумать что постфиксный ++ не требует l-value, но такие конструкции тоже не работают:


А>
 
А>++(С+1) // в обоих случаях попытка применить
А>(С+1)++ // оператор (пре/пост)инкремента к rvalue
А>


А>P.S. В C# этой фичи нет.
Re: Почему в С++ можно ставить плюсы перед ++С...
От: Dmitry Kotlyarov Россия  
Дата: 14.07.06 15:03
Оценка: 1 (1)
Здравствуйте, Ароан, Вы писали:

А>Объясните почему на C++ работает следующая конструкция:


А>
А>(++С)++ // ++C - l-value, все правильно
А>


А>А вот такая не работает:


А>
А>++(С++) // C++ - r-value, а префиксный ++ принимает l-value
А>


А>Можно подумать что постфиксный ++ не требует l-value, но такие конструкции тоже не работают:


А>
А>++(С+1) // здесь C+1 - r-value,
А>(С+1)++ // а обе формы инкремента принимают l-value
А>


А>P.S. В C# этой фичи нет.


Префиксный ++ принимает l-value и возвращает l-value.
Постфиксный ++ тоже принимает l-value и возвращает r-value.
Re: Почему в С++ можно ставить плюсы перед ++С...
От: pullover  
Дата: 14.07.06 14:53
Оценка:
Здравствуйте, Ароан, Вы писали:

А>Объясните почему на C++ работает следующая конструкция:


А>
А>(++С)++
А>


А>А вот такая не работает:


А>
А>++(С++)
А>


А>Можно подумать что постфиксный ++ не требует l-value, но такие конструкции тоже не работают:


А>
А>++(С+1)
А>(С+1)++
А>


А>P.S. В C# этой фичи нет.



как правило постфиксная форма такая:

const Т Т::operator++(int)
Re: Почему в С++ можно ставить плюсы перед ++С...
От: FoolS.Top Армения  
Дата: 14.07.06 15:03
Оценка:
Здравствуйте, Ароан, Вы писали:

А>Объясните почему на C++ работает следующая конструкция:


А>
А>(++С)++
А>


А>А вот такая не работает:


А>
А>++(С++)  // 'C++' не является l-value
А>


А>Можно подумать что постфиксный ++ не требует l-value, но такие конструкции тоже не работают:


А>
А>++(С+1)  // 'C + 1' не является l-value
А>(С+1)++  // 'C + 1' не является l-value
А>


А>P.S. В C# этой фичи нет.


++ требует l-value
Feierlich, misterioso
Re[2]: Почему в С++ можно ставить плюсы перед ++С...
От: Ароан Россия  
Дата: 14.07.06 15:22
Оценка:
Ну вроде понятно стало.

Получается, что можно написать так:
(++y) = x;


А так нет:
(y++) = x;


Но возникает другой вопрос, зачем все это надо?
Есть ли какая-то разумная причина возвращать l-value?
Re[3]: Почему в С++ можно ставить плюсы перед ++С...
От: Кодт Россия  
Дата: 14.07.06 15:42
Оценка:
Здравствуйте, Ароан, Вы писали:

А>Есть ли какая-то разумная причина возвращать l-value?

Да: двойной автоинкремент. ++ ++ x
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Перекуём баги на фичи!
Re[3]: Почему в С++ можно ставить плюсы перед ++С...
От: Константин Л. Франция  
Дата: 14.07.06 16:36
Оценка:
Здравствуйте, Ароан, Вы писали:

А>Ну вроде понятно стало.


А>Получается, что можно написать так:

А>
А>(++y) = x;
А>


А>А так нет:

А>
А>(y++) = x;
А>


А>Но возникает другой вопрос, зачем все это надо?

А>Есть ли какая-то разумная причина возвращать l-value?

дело в том, что ()++ работает с "задержкой", те инкремент происходит, но должен возвращаться временный объект
Re: Почему в С++ можно ставить плюсы перед ++С...
От: Молодой Россия  
Дата: 15.07.06 06:47
Оценка:
Здравствуйте, Ароан, Вы писали:

А>Объясните почему на C++ работает следующая конструкция:


А>
А>(++С)++
А>


А>А вот такая не работает:


А>
А>++(С++)
А>


in fact, internal implementation of postfix operator ++ returns r-value,
preffix operator ++ requires l-value and none r-values can be converted to l-values,
but l-values can be converted to r-values.
in the statement like ++a++ => ++(a++) we have following operator precedence:
first will be availuated postfix ++, then its returned r-value will be passed to preffix ++
as it was said, none r-value can be converted to l-value,
in case of ++(a++) you just did the statement more clear for guys how does not know operator precedence rules
but not changed the way statement ++a++ is avaluated.

UDTs can have their own postfix and preffix operators, so that it would be possible
to write ++a++ if a is an instance of UDT type.
That's it!

PS:
For your information:
An object is a contiguous region of storage. An lvalue is an expression that refers to such an object. The original
definition of lvalue referred to an object that can appear on the left-hand side of an assignment. However, const
objects are lvalues that cannot be used in the left-hand side of an assignment. Similarly, an expression that can appear
in the right-hand side of an expression (but not in the left-hand side of an expression) is an rvalue.
An lvalue can appear in a context that requires an rvalue; in this case, the lvalue is implicitly converted to an rvalue.
An rvalue cannot be converted to an lvalue. Therefore, it is possible to use every lvalue expression in the example as
an rvalue, but not vice versa.

PPS
Sorry for using English, don't have a localized keyboard on this machine.
Re[2]: Почему в С++ можно ставить плюсы перед ++С...
От: Ароан Россия  
Дата: 17.07.06 08:39
Оценка:
Зачем возвращать l-value я понял. Но тогда возникает еще один вопрос.
Есть ли какая-то разумная причина возвращать r-value?

В своем классе у меня этого не получилось сделать. Если без ссылки — временный объект создается и получаем l-value. Если возвращать по ссылке — временный объект не создается и все равно получаем l-value.

Можно написать как угодно ++С++, (++С)++, ++(С++).

class A
{
public:
    int x;
    
    A(int i) 
    { 
        x=i; 
        cout << "A(" << x << ")" << endl; 
    }
    
    ~A() 
    { 
        cout << "~A" << endl; 
    }

    A(A &a) 
    { 
        x=a.x; 
        cout << "A(&" << x << ")" << endl; 
    }

    A& operator ++()
    {
        x++;
        cout << "++() -> " << x << endl;
        return *this;
    }

    A& operator ++(int)
    {
        x++;
        cout << "()++ -> " << x << endl;
        return *this;
    }
};
Re[3]: Почему в С++ можно ставить плюсы перед ++С...
От: ekamaloff Великобритания  
Дата: 17.07.06 08:56
Оценка:
Здравствуйте, Ароан, Вы писали:

<...>

У тебя вообще-то нарушена семантика постфиксного ++. Дожно быть примерно так (и в таком случае как раз приходится возвращать rvalue):

А>
А>class A
А>{
А>public:
А>    int x;
A>    //...
А>    A operator ++(int)
А>    {
A>        A tmp(*this);
А>        ++(*this);
А>        return tmp;
А>    }
А>};
А>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.