Що робить оператор unary plus? Є кілька визначень, які я знайшов ( тут і тут ), але я досі не уявляю, для чого це буде використовуватися. Здається, це нічого не робить, але на це є причина, так?
Відповіді:
Це є для перевантаження, якщо ви відчуваєте потребу; для всіх попередньо визначених типів це, по суті, заборона.
Практичне використання неофіційного одинарного арифметичного оператора досить обмежене і, як правило, пов'язане з наслідками використання значення в арифметичному виразі, а не з самим оператором. Наприклад, його можна використовувати для примусового розширення з менших інтегральних типів до int
або для забезпечення того, щоб результат виразу оброблявся як значення r і, отже, не сумісний з нереференсним 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 - це 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. Це може бути дуже корисно, якщо ви намагаєтесь надрукувати дані символів, використовуючи 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
Це лише короткий приклад. Я впевнений, бувають інші випадки, коли unary + може допомогти розглядати ваші байти більше як цифри, а не як текст.
Історичний ласощі. Комітет стандартизації C99 також вважав, що існуючі варіанти використання унарних плюсів були досить рідкісними, про що свідчить їх розгляд можливості повторного використання його для досягнення ще однієї особливості мови: гальмування оцінки часу перекладу константних виразів із плаваючою комою. Див. Наступну цитату з обґрунтування С, розділ F.7.4:
Рання версія цієї специфікації дозволяла арифметику константи часу перекладу, але надала можливість оператору unary +, коли застосовується до операнда, перешкоджати оцінці часу перекладу константних виразів.
Врешті-решт, семантика була змінена, при цьому в більшості контекстів було застосовано оцінку часу виконання (принаймні до правила «як би»), і можливість примусити оцінку часу перекладу за допомогою статичних ініціалізаторів. Зверніть увагу, що основна відмінність полягає у виникненні винятків із плаваючою комою та інших параметрах округлення або точності з плаваючою точкою, де вони є.
Не багато. Загальний аргумент, що дозволяє перевантаження, operator+()
полягає в тому, що, безумовно, існують реальні способи використання перевантаження operator-()
, і було б дуже дивно (або асиметрично), якщо б ви дозволили перевантаження, operator-()
але ні operator+()
.
Я вважаю, що вперше прочитав цей аргумент у "Строустроп", але не маю при собі своїх книг для підтвердження. Я можу помилятися.
Унарний плюс був присутній у C, де він абсолютно нічого не робив (приблизно як auto
ключове слово). Щоб його не мати, Страуструпу довелося б запровадити безоплатну несумісність із C.
Як тільки це було в C ++, було природно дозволити функцію перевантаження, як і одинарний мінус, і Stroustrup міг би ввести її з цієї причини, якби її там ще не було.
Отже, це нічого не означає. Він може бути використаний як вид прикраси, щоб зробити речі більш симетричними, використовуючи +1,5, як протилежність -1,5, наприклад. У C ++ він може бути перевантажений, але це буде заплутати, якщо operator+()
щось зробить. Запам’ятайте стандартне правило: перевантажуючи арифметичні оператори, виконуйте такі дії, як int
s.
Якщо ви шукаєте причину, чому вона там, знайдіть щось про ранню історію 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)
Звичайно, це з моєї інтерпретації примітки в одному з посібників для 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;
}
Як показано у прикладі вище, unary + дійсно змінює тип, розміри 4 та 2 відповідно. Дивно, що вираз + x справді обчислюється в розміріof, я думав, що це не повинно було. Можливо, це пов'язано з тим, що sizeof має такий же пріоритет, як і unary +.
Думаю, ви могли б використовувати його, щоб завжди зробити число позитивним. Просто перевантажте унарний + оператор, щоб бути абс. Насправді не варто плутати колег-розробників, якщо ви насправді просто не хочете заплутати свій код. Тоді це добре працювало б.
~
? Я не впевнений, що таке ваше визначення "протилежне", але я підозрюю, що це упереджено досвідом того, що в даний час роблять одинарний плюс і одинарний мінус.
EDIT Переписав повністю, тому що я був 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})