Что делает унарный оператор плюс? - PullRequest
71 голосов
/ 08 апреля 2009

Что делает унарный оператор плюс? Я нашел несколько определений ( здесь и здесь ), но я до сих пор не представляю, для чего он будет использоваться. Кажется, это ничего не делает, но для этого есть причина, верно?

Ответы [ 14 ]

102 голосов
/ 11 октября 2010

На самом деле, унарный плюс делает что-то делает - даже в C. Он выполняет обычные арифметические преобразования над операндом и возвращает новое значение, которое может быть целым числом большей ширины. Если исходное значение было целым числом без знака меньшей ширины, чем int, оно также будет изменено на значение signed.

Обычно это не так важно, но может иметь эффект, поэтому не хорошая идея использовать унарный плюс как своего рода «комментарий», обозначающий, что целое число положительное. Рассмотрим следующую программу на C ++:

void foo(unsigned short x)
{
 std::cout << "x is an unsigned short" << std::endl;
}

void foo(int x)
{
 std::cout << "x is an int" << std::endl;
}

int main()
{
 unsigned short x = 5;
 foo(+x);
}

Появится «x - это int».

Так что в этом примере унарный плюс создал новое значение с типом и подписи.

53 голосов
/ 08 апреля 2009

Это должно быть перегружено, если вы чувствуете необходимость; для всех предопределенных типов это, по сути, запрет.

Практическое использование неоперативного арифметического оператора довольно ограничено и, как правило, связано с последствиями использования значения в арифметическом выражении, а не с самим оператором. Например, его можно использовать для принудительного расширения от меньших целочисленных типов до int или для обеспечения того, чтобы результат выражения обрабатывался как значение r и, следовательно, не был совместим с не const ссылочным параметром. Я утверждаю, однако, что эти виды использования лучше подходят для кодирования гольфа, чем для удобства чтения. : -)

33 голосов
/ 30 сентября 2011

Из второго издания K & R:

Унарный + является новым стандартом ANSI. Был добавлен для симметрии с одинарным -.

31 голосов
/ 08 апреля 2009

Я видел, что это используется для ясности, чтобы подчеркнуть положительное значение в отличие от отрицательного значения:

shift(+1);
shift(-1);

Но это довольно слабое применение. Ответ определенно перегружен.

24 голосов
/ 11 октября 2010

Единственное, что делает встроенный унарный +, это превращает lvalue в rvalue. Например, вы можете сделать это

int x;
&x;

но вы не можете сделать это

&+x;

:)

P.S. «Перегрузка» - определенно не правильный ответ. Унарный + был унаследован от C и в C. нет никаких перегрузок операторов пользовательского уровня.

14 голосов
/ 11 октября 2010

Главное, что выполняет unary +, - это продвижение типов в int для типов данных меньше, чем int. Это может быть очень полезно, если вы пытаетесь напечатать данные символа, используя std::cout в качестве числовых данных.

char x = 5;
std::cout << +x << "\n";

очень отличается от

char x=5;
std::cout << x << "\n";

Он также доступен для перегрузки, но на практике ваша перегрузка должна быть почти NOP.

10 голосов
/ 05 августа 2012

Если вам когда-либо понадобится напечатать числовое значение необработанных байтов (например, небольшие числа, хранящиеся в виде символов) для отладки или по любой другой причине, unary + может упростить код печати. Рассмотрим

char c = 42;
cout << c << endl;           // prints "*\n", not what you want in this case
cout << (int)c << endl;      // prints "42\n", ok
cout << +c << endl;          // prints "42\n", much easier to type

Это всего лишь быстрый пример. Я уверен, что бывают другие случаи, когда унарный + может помочь обрабатывать ваши байты больше как числа, а не как текст.

4 голосов
/ 16 июля 2012

Исторический лакомый кусочек. Комитет по стандартизации C99 также полагал, что существующие варианты использования унарного плюса были довольно редкими, о чем свидетельствует их возможность повторно использовать его для достижения другой функции в языке: запрещение оценки времени перевода константных выражений с плавающей точкой. См. Следующую цитату из Обоснования C, раздел F.7.4:

Ранняя версия этой спецификации допускала постоянную арифметику времени перевода, но уполномочил унарный оператор + при применении к операнду, чтобы запретить время перевода оценка константных выражений.

В конце семантика была полностью изменена, с оценкой во время выполнения, применяемой в большинстве контекстов (по крайней мере, до правила «как если бы»), и способностью выполнять оценку времени перевода с использованием статических инициализаторов. Обратите внимание, что основное различие заключается в возникновении исключений с плавающей запятой и других параметров округления или точности с плавающей запятой, если таковые имеются.

3 голосов
/ 10 апреля 2009

Унарный плюс присутствовал в C, где он абсолютно ничего не делал (очень похоже на ключевое слово auto). Чтобы этого не было, Страуструпу пришлось бы ввести безвозмездную несовместимость с C.

Когда-то это было в C ++, было естественно разрешить функцию перегрузки, как унарный минус, и Страуструп мог бы ввести ее по этой причине, если бы ее еще не было.

Итак, это ничего не значит. Его можно использовать как декорацию, чтобы сделать вещи более симметричными, например, используя +1,5 в качестве противоположности -1,5. В C ++ он может быть перегружен, но это будет сбивать с толку, если operator+() что-нибудь сделает. Помните стандартное правило: при перегрузке арифметических операторов делайте что-то вроде int s.

Если вы ищете причину, по которой он существует, найдите кое-что о ранней истории C. Я подозреваю, что не было веской причины, так как C не был действительно разработан. Рассмотрим бесполезное ключевое слово auto (предположительно в отличие от static, которое теперь перерабатывается в C ++ 0x) и ключевое слово entry, которое никогда ничего не делало (а позже в C90 опущено). Есть известное электронное письмо, в котором Ритчи или Керниган говорят, что, когда они поняли, что у приоритета оператора возникли проблемы, уже было три установки с тысячами строк кода, которые они не хотели нарушать.

3 голосов
/ 10 апреля 2009

Не очень. Общий аргумент для разрешения перегрузки operator+() заключается в том, что для перегрузки operator-() определенно существует реальный мир, и было бы очень странно (или асимметрично), если бы вы разрешили перегрузку operator-() но не operator+().

Я полагаю, что впервые прочитал этот аргумент из Страустропа, но у меня нет с собой книг, чтобы проверить это. Я могу ошибаться.

...