Вопрос

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

Это было полезно?

Решение

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

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

Другие советы

На самом деле, унарный плюс делает сделайте что - нибудь - даже в 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".

Итак, в этом примере unary plus создал новое значение с другим типом и подписанность.

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

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

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

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

Но это довольно слабое применение.Ответ, безусловно, заключается в перегрузке.

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

int x;
&x;

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

&+x;

:)

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

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

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

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

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

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

Если вам когда-нибудь понадобится напечатать числовое значение необработанных байтов (например, небольшие числа, сохраненные в виде символа) для отладки или по какой-либо другой причине, 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 также счел, что существующее использование унарного плюс было довольно редким, о чем свидетельствует их рассмотрение повторного использования для достижения другой функции в языке:запрещение вычисления констант с плавающей запятой во время трансляции.Смотрите следующую цитату из Обоснования C, раздел F.7.4:

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

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

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

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

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

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

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

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

Я не могу привести какой-либо источник для этого, но я пришел к пониманию, что это для явного продвижения типа, что подразумевает преобразование типа без потерь.Это ставит его на вершину иерархии конверсий,

  • Продвижение по службе: new_type operator+(old_type)
  • Преобразование: new_type(old_type)
  • Бросок: operator(new_type)(old_type)
  • Принуждение: new_type operator=(old_type)

Конечно, это из моей интерпретации примечания в одном из руководств Microsoft (действительно старых) по c / c ++, которое я прочитал около 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 имеет тот же приоритет, что и унарный +.

Я полагаю, вы могли бы использовать это, чтобы всегда делать число положительным.Просто перегрузите унарный оператор +, чтобы он был abs.На самом деле не стоит сбивать с толку ваших коллег-разработчиков, если только вы действительно просто не хотите запутать свой код.Тогда это сработало бы прекрасно.

Редактировать Переписал полностью, потому что я был ваааайый не прав в своем первоначальном ответе.

Это должно позволить вам обрабатывать явное объявление вашего типа как положительное значение (я думаю, в основном в нематематических операциях).Кажется, что отрицание было бы более полезным, но я думаю, вот пример того, где это может иметь значение:

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; }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top