Какова цель унарного «+» перед вызовом членов std :: numeric_limits <unsigned char>?

130

Я видел этот пример в документации cppreference дляstd::numeric_limits

#include <limits>
#include <iostream>

int main() 
{
    std::cout << "type\tlowest()\tmin()\t\tmax()\n\n";

    std::cout << "uchar\t"
              << +std::numeric_limits<unsigned char>::lowest() << '\t' << '\t'
              << +std::numeric_limits<unsigned char>::min() << '\t' << '\t'
              << +std::numeric_limits<unsigned char>::max() << '\n';
    std::cout << "int\t"
              << std::numeric_limits<int>::lowest() << '\t'
              << std::numeric_limits<int>::min() << '\t'
              << std::numeric_limits<int>::max() << '\n';
    std::cout << "float\t"
              << std::numeric_limits<float>::lowest() << '\t'
              << std::numeric_limits<float>::min() << '\t'
              << std::numeric_limits<float>::max() << '\n';
    std::cout << "double\t"
              << std::numeric_limits<double>::lowest() << '\t'
              << std::numeric_limits<double>::min() << '\t'
              << std::numeric_limits<double>::max() << '\n';
}

Я не понимаю оператор "+" в

<< +std::numeric_limits<unsigned char>::lowest()

Я протестировал его, заменил на «-», и это тоже сработало. Какая польза от такого оператора "+"?

Zhang
источник
3
Попытайся. Что вы получите, если не укажете +?
Пит Беккер
4
Этот вопрос не нужно было бы задавать, если бы автор кода заботился о том, чтобы объяснить, что это означает, или вместо этого использовал бы явное приведение ...
user202729 03
если вы замените на, -то выходные данные не будут соответствовать правильным значениям для пределов
phuclv
1
Для справки: если вы хотите найти в себе подобные вещи в Google, это называется оператором «унарный плюс» - он унарный, потому что он принимает одно значение (в данном случае, вещь сразу после него) и «плюс». "- это удобный способ сказать Google +. В этом случае ваш запрос, вероятно, будет «c ++ unary plus». Это ... не совсем интуитивно понятно, и вам все равно придется научиться читать документацию, которую вы найдете, но, IMO, это полезный навык для развития.
Иск Фонда Моники

Ответы:

137

Оператор вывода <<при передаче char(со знаком или без знака) запишет его как символ .

Эти функции будут возвращать значения типа unsigned char. И, как отмечалось выше, будут печататься символы, которые эти значения представляют в текущей кодировке, а не их целочисленные значения.

В +операторе преобразует unsigned charвозвращаемый эти функции к intчерез продвижение целого . Это означает, что вместо этого будут напечатаны целые значения.

Выражение like +std::numeric_limits<unsigned char>::lowest()по существу равно static_cast<int>(std::numeric_limits<unsigned char>::lowest()).

Какой-то программист чувак
источник
37

+есть, чтобы превратить unsigned charв int. +Оператор значение сохранения, но она имеет эффект индукции интегрального продвижения на операнде. Это необходимо для того, чтобы вы видели числовое значение вместо некоторого (полу) случайного символа, который operator <<будет печататься при заданном типе символа.

Рассказчик - Незеленка Моника
источник
18

Просто чтобы добавить ссылку на уже данные ответы. Из стандартного рабочего проекта CPP N4713 :

8.5.2.1 Унарные операторы
...

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

И char, short, intи longявляются неотъемлемыми типами.

PW
источник
12

Без +результата будет иначе. Следующий фрагмент выводит a 97вместоa a

char ch = 'a';
std::cout << ch << ' ' << +ch << '\n';

Причина в том, что разные перегрузки печатают разные типы данных . Нет basic_ostream& operator<<( char value );перегрузки для, std::basic_ostreamи это объясняется в конце страницы

Аргументы символов и символов строк (например, типа charили const char*) обрабатываются по перегрузкам , не являющихся членами в operator<<. Попытка вывести символ с использованием синтаксиса вызова функции-члена (например, std::cout.operator<<('c');) вызовет одну из перегрузок (2-4) и выведет числовое значение . Попытка вывести символьную строку с использованием синтаксиса вызова функции-члена вызовет перегрузку (7) и вместо этого напечатает значение указателя.

От перегрузки , не являющийся членом , который будет вызываться при передаче charпеременного

template< class CharT, class Traits> basic_ostream<CharT,Traits>& operator<<(
    basic_ostream<CharT,Traits>& os, char ch );

который печатает символ в кодовой точке ch

Поэтому в основном , если вы передаете char, signed charили unsigned charнепосредственно в потоке он будет печатать персонаж. Если вы попытаетесь удалить в +приведенных выше строках, вы увидите, что он печатает некоторые «странные» или невидимые символы, чего нельзя было ожидать.

Если вы хотите их числовые значения вместо этого вы должны вызвать перегрузку для short, int,long или long long. Самый простой способ сделать это - charперейти intс на с унарным плюсом +. Это один из редких полезных приложений в унарный плюс . Явное приведение к intтакже будет работать

Есть много людей, которые столкнулись с этой проблемой на SO like

phuclv
источник
1
Вы имели в виду унарный плюс , а не минус?
Руслан