Что делает унарный плюс? Есть несколько определений, которые я нашел ( здесь и здесь ), но я до сих пор не знаю, для чего они будут использоваться. Похоже, он ничего не делает, но для этого есть причина, верно?
Ответы:
Его нужно перегружать, если вы чувствуете в этом необходимость; для всех предопределенных типов это практически не работает.
Практическое использование унарного арифметического оператора без операций довольно ограничено и, как правило, связано с последствиями использования значения в арифметическом выражении, а не с самим оператором. Например, его можно использовать для принудительного расширения от меньших целочисленных типов до int
или для обеспечения того, чтобы результат выражения обрабатывался как rvalue и, следовательно, не был совместим с const
параметром, не являющимся ссылкой. Я утверждаю, однако, что эти варианты использования лучше подходят для программирования гольфа, чем удобочитаемость. :-)
int
rvalue и его результат являются эффектами выражения -ness, а не самого оператора +.
На самом деле, унарный плюс это сделать что - то - даже в 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 is an int».
Итак, в этом примере унарный плюс создал новое значение с другим типом и подписью.
an integer of greater width
?
Я видел, как это используется для ясности, чтобы подчеркнуть положительное значение в отличие от отрицательного значения:
shift(+1);
shift(-1);
Но это довольно слабое применение. Ответ определенно перегружает.
vec3(+1,-1,-1)
Одна вещь, которую +
делает встроенный унарный , - это превращение lvalue в rvalue. Например, вы можете сделать это
int x;
&x;
но ты не можешь этого сделать
&+x;
:)
PS "Перегрузка" точно не правильный ответ. Unary +
был унаследован от C, и в C. нет перегрузки оператора пользовательского уровня.
Главное, что выполняет unary +, - это преобразование типа в int для типов данных меньшего, чем int. Это может быть весьма полезно, если вы пытаетесь распечатать данные типа char, используя std::cout
как числовые данные.
char x = 5;
std::cout << +x << "\n";
сильно отличается от
char x=5;
std::cout << x << "\n";
Он также доступен для перегрузки, но на практике ваша перегрузка должна быть почти NOP.
Если вам когда-нибудь понадобится распечатать числовое значение необработанных байтов (например, небольшие числа, сохраненные как char) для отладки или по любой другой причине, 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
Это всего лишь краткий пример. Я уверен, что бывают и другие случаи, когда унарный + может помочь обработать ваши байты больше как числа, а не как текст.
Исторический лакомый кусочек. Комитет по стандартизации C99 также считал, что существующее использование унарного плюса было довольно редким, о чем свидетельствует их повторное использование его для достижения другой функции языка: запрета оценки времени перевода константных выражений с плавающей запятой. См. Следующую цитату из Обоснования языка Си, раздел F.7.4:
Ранняя версия этой спецификации позволяла выполнять арифметические операции с константами времени трансляции, но давала возможность унарному оператору + при применении к операнду запрещать вычисление константных выражений во время трансляции.
В конце концов, семантика была изменена на противоположную: оценка времени выполнения применялась в большинстве контекстов (по крайней мере, до правила «как если бы»), и появилась возможность принудительно выполнять оценку времени перевода с помощью статических инициализаторов. Обратите внимание, что основное различие заключается в возникновении исключений с плавающей запятой и других параметрах округления или точности с плавающей запятой, если они есть.
Немного. Общий аргумент в пользу разрешения перегрузки operator+()
состоит в том, что определенно существуют реальные способы использования перегрузки operator-()
, и было бы очень странно (или асимметрично), если бы вы разрешили перегрузку, operator-()
но не разрешили бы operator+()
.
Мне кажется, что я впервые прочитал этот аргумент Страустропа, но у меня нет с собой книг, чтобы проверить его. Я могу быть не прав.
Унарный плюс присутствовал в C, где он абсолютно ничего не делал (как и auto
ключевое слово). Чтобы этого не произошло, Страуструпу пришлось бы ввести бесплатную несовместимость с C.
Когда-то это было в C ++, было естественно разрешить функцию перегрузки, как и унарный минус, и Страуструп мог ввести ее по этой причине, если бы ее еще не было.
Итак, это ничего не значит. Его можно использовать как своего рода украшение, чтобы вещи выглядели более симметрично, например, используя +1,5 в качестве противоположности -1,5. В C ++ он может быть перегружен, но это может сбить с толку operator+()
. Помните стандартное правило: при перегрузке арифметических операторов выполняйте такие действия, какint
s do.
Если вы ищете причину, по которой он существует, найдите что-нибудь о ранней истории C. Я подозреваю, что не было веской причины, поскольку C на самом деле не был разработан. Рассмотрим бесполезное auto
ключевое слово (предположительно в отличие от того static
, которое сейчас используется в C ++ 0x), и entry
ключевое слово, которое никогда ничего не делало (и позже опущено в C90). Есть известное электронное письмо, в котором Ричи или Керниган говорят, что, когда они поняли, что приоритет оператора имеет проблемы, уже было три установки с тысячами строк кода, которые они не хотели нарушать.
entry
: ( stackoverflow.com/q/254395/153285 ). В наши дни, если вам нужно несколько точек входа, просто используйте хвостовые вызовы и оптимизацию на основе профиля.
extern volatile int foo;
, что компилятор с данным оператором +foo;
должен будет выполнить чтение указанного адреса на любой платформе, где предположительно могут существовать какие-либо средства для определения того, что чтение имело место. Я не уверен, что это потребовалось бы, если бы оператор был просто "foo", хотя многие компиляторы сделают это из любезности.
Я не могу указать какой-либо источник для этого, но я понял, что это для явного продвижения типа, что подразумевает преобразование типа без потерь. Это помещает его на вершину иерархии конверсий,
new_type operator+(old_type)
new_type(old_type)
operator(new_type)(old_type)
new_type operator=(old_type)
Конечно, это из моей интерпретации примечания в одном из (действительно старых) руководств по c / c ++ Microsoft, которое я прочитал около 15 лет назад, так что относитесь к нему с недоверием.
#include <stdio.h>
int main()
{
unsigned short x = 5;
printf ("%d\n",sizeof(+x));
printf ("%d\n",sizeof(x));
return 0;
}
Как показано в примере выше, унарный + действительно меняет тип, размер 4 и 2 соответственно. Странно, что выражение + x действительно вычисляется в sizeof, я думал, что этого не должно было быть. Возможно, это связано с тем, что sizeof имеет тот же приоритет, что и унарный +.
Я полагаю, вы могли бы использовать его, чтобы всегда делать число положительным. Просто перегрузите унарный оператор +, чтобы он был абс. На самом деле не стоит сбивать с толку коллег-разработчиков, если только вы не хотите просто запутать свой код. Тогда это прекрасно сработает.
~
? Я не уверен, каково ваше определение «противоположности», но подозреваю, что оно основано на опыте того, что в настоящее время делают унарный плюс и унарный минус.
РЕДАКТИРОВАТЬ Переписано полностью, потому что в моем первоначальном ответе я был waaaayyy.
Это должно позволить вам обрабатывать явное объявление вашего типа как положительное значение (я думаю, что это в основном нематематические операции). Кажется, что отрицание было бы более полезным, но я думаю, вот пример того, где это может иметь значение:
public struct Acceleration
{
private readonly decimal rate;
private readonly Vector vector;
public Acceleration(decimal rate, Vector vector)
{
this.vector = vector;
this.rate = rate;
}
public static Acceleration operator +(Acceleration other)
{
if (other.Vector.Z >= 0)
{
return other;
}
return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
}
public static Acceleration operator -(Acceleration other)
{
if (other.Vector.Z <= 0)
{
return other;
}
return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
}
public decimal Rate
{
get { return rate; }
}
public Vector Vector
{
get { return vector; }
}
}
+
не в том, чтобы сделать значение положительным, а оставить его знак неизменным.
просто это используется, чтобы убедить, какие числа положительны
например;
int a=10;
System.out.println(+x);// prints 10(that means,that number 10 multiply by +1,{10*+1})
//if we use unary minus
int a=10;
System.out.println(-x);//prints -10(that means,that number 10 multiply by +1,{10*-1})