Чи є дужки навколо результату значущими у операторі повернення?


79

Чи існує різниця між цими двома твердженнями всередині функції?

bool returnValue = true;
// Code that does something
return(returnValue);

і це?

bool returnValue = true;
// Code
return returnValue;

Перший має дужки навколо returnValue.


Дякую Роб, ти успішно захопив дух питання. В Essence мені було цікаво, чи зробив компілятор щось особливе (наприклад, спробу спочатку оцінити вираз), чи він просто його проігнорував.
Хосе Вільялта

1
На це питання важко відповісти будь-якому c++ / c. Було б непогано визначитися з визначенням мови, але я не знаю, як це виправити через 9 років.
Jonas Stein

Адже Cіснує дублікат stackoverflow.com/questions/161879/…
Jonas Stein

Відповіді:


122

Починаючи з C ++ 14, вони часто є.

C ++ 14 додає регістр, де дужки навколо поверненого значення можуть змінити семантику. Цей фрагмент коду показує дві оголошені функції. Різниця лише в дужках навколо поверненого значення.

int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))

У першому func1повертає a, intа в другому - func1an int&. Різниця в семантиці безпосередньо пов’язана з оточуючими дужками .

Специфікатор autoв останній формі був введений в C ++ 11. У мовній специфікації C ++ це описується як:

Вказує, що тип змінної, яка оголошується, буде автоматично виведений з її ініціалізатора. Для функцій вказує, що тип повернення є кінцевим типом повернення або буде виводитися з його операторів повернення (оскільки C ++ 14)

Окрім того, C ++ 11 представив decltypeспецифікатор, який описаний в мовній специфікації C ++ :

Перевіряє оголошений тип сутності або запитує тип повернення виразу.

[сніп]

  1. Якщо аргументом є або непрозоре ім'я об'єкта / функції, або вираз доступу до члена (object.member або pointer-> member), тоді decltype вказує оголошений тип сутності, вказаний цим виразом.

  2. Якщо аргументом є будь-який інший вираз типу T, тоді

    а) якщо категорією значень виразу є xvalue, тоді тип declt визначає T&&

    б) якщо категорією значень виразу є lvalue, тоді тип declt визначає T &

    в) інакше decltype визначає T

[сніп]

Зверніть увагу, що якщо ім’я об’єкта в дужках, воно стає виразом lvalue, таким чином decltype (arg) та decltype ((arg)) часто бувають різних типів.

У C ++ 14 можливість використання decltype(auto)була дозволена для типів повернених функцій. Оригінальні приклади - це семантична різниця з дужками. Перегляд оригінальних прикладів:

int var1 = 42;
decltype(auto) func1() { return var1; } // return type is int, same as decltype(var1)
decltype(auto) func1() { return(var1); } // return type is int&, same as decltype((var1))

decltype(auto)дозволяє завершуючий тип повернення у функції виводитись із сутності / виразу в операторі return. У першій версії return var1;це фактично те саме, що повернення типу decltype(var1)( тип intповернення за правилом 1 вище), а у другому випадку return (var1);це фактично те саме, що decltype((var1))( int &тип повернення за правилом 2b).

Дужки роблять тип повернення int&замість int, таким чином, змінюючи семантику. Мораль історії - "Не всі дужки типу повернення створені рівними"


Оператор return без дужок все ще є виразом lvalue, так? Якщо це не трактується як xvalue у цьому сценарії. Чи можете ви пояснити ціннісну категорію повернення без дужок?
void.pointer

1
Оператор return повертає зчитування поданого в нього виразу, тобто він фіксує значення r із виразу, який він містить, і повертає це. Ми ніколи не повертаємо значення. Можливо, у якогось компілятора є помилка, яка відповідає опису, який ви даєте тут, і з причин, які ви тут подаєте, але це ніколи не повинно бути випадком, що return (x);еквівалентно return &x;, і не повинно бути можливим, щоб це призвело до повернення значення x, але з посиланням на тип x.
Теодор Мердок,

4
Ого, яка жахлива конструкція мови. Просто повністю ... непрозорий. Хороший запис, хоча, дякую.
Пол Сандерс,

5
C ++ - надзвичайно цікава мова. Але подібні приховані "особливості" іноді
збивають

Наш код переповнений цими непотрібними дужками. Ми також часто використовуємо auto. Чи наша семантика ніколи не змінюється, поки ми тримаємось подалі decltype? Я боюся несподіваної поведінки, коли ми переходимо до наступної версії компілятора, яка включає наступну Visual Studio.
OneWorld

6

Різниці немає.

Однією з причин використання дужок було б, якщо ви хочете обчислити вираз перед поверненням, але у вашому прикладі причин не буде. Подивитися:

Дужки навколо повернутих значень

для подальшого обговорення.


3
Хоча навіть із складним виразом, ці дужки все одно не викликають іншої поведінки. Вони просто роблять значення більш очевидним (суб’єктивно!) Для читачів.
aschepler

@Karl "Однією з причин використання дужок буде, якщо ви хочете оцінити вираз перед поверненням". Чи можете ви навести приклад цього?
Кріс Міддлтон

3
@ChrisMiddleton Ні, оскільки претензія тут така ж безглузда, як і в цій темі. Немає ніякої функціональної різниці між return m * x + cта return (m * x + c)чи return ( (m * x) + c )або, тощо - і це не виглядає ні кращим, ні інтуїтивнішим, якщо ви запитаєте мене.
underscore_d

5

Дужки у верхньому прикладі зайві; вони фактично ігноруються.

Це було б так само, як щось на зразок ...

int x = (5);

Дужки тут також ігноруються.


Ну, технічно вони не ігноруються , вони просто не впливають на значення виразу.
Джон Боде,

1
@ Джон: фактично ігнорується. :)
Джеймс

3
+1 ... це єдина відповідь, яка стверджує, що дужки насправді зайві, і показує, що їх використання трохи дурне.
Конрад Рудольф

4

AFAIK, нічого не відрізняється.

У C ++ вирази можуть мати вигляд: exprабо (expr). Отже, останнє - вираз з більшою кількістю набору тексту. Для подальшого читання про це зверніться до граматики (шукайте "вираз").


Девід, дякую за посилання. У мене є граматика в книзі С ++ Струструпа, але (мабуть, з-за лінощів) я не дивлюся на неї так сильно, тепер, коли у мене є закладка в моєму браузері, я можу звертатися до неї частіше.
Хосе Віллалта


3

Я припускаю boo, що це друкарська помилка, і ви запитуєте, чи є різниця між

return expr;

і

return(expr);

Відповідь - ні.


2

Без різниці!!

Люди використовують дужки, якщо йдеться про складний вираз.

BTW return- це твердження, а не функція.


2

Ні, між ними немає різниці, хоча ви можете включити дужки, якщо це робить вираз легким для читання та зрозумілістю.


1
... але ніколи цього не відбувається. Чому б? Що важко прочитати про неприхований вираз? Додавання дужок просто здається мені безладом. Що стосується того, що здається яснішим, чи думають люди returnпро жадібного оператора, який return m * x + cможе повернутися mі відкинути решту, чи що?
underscore_d

1

Ви грубо гальмуєте компілятор!

Наявність дужок не тільки уповільнює фазу попередньої обробки, але вони також генерують більш складне Дерево абстрактного синтаксису: більше пам'яті, більше обчислень.


З семантичної точки зору? Вони абсолютно ідентичні. Незалежно від того, є дужки чи ні, returnоператор повністю оцінить вираз перед його поверненням.


5
Моє мислення точно. Змушуючи компілятор робити непотрібну роботу, аналізуючи марну метушню, він наближається до теплової смерті Всесвіту без поважних причин.
Максим Єгорушкін

4
Як ви ставитеся до біткойнів?
Jeremy Nikolai

0

Вони однакові. Я бачу синтаксис дужок досить часто, і я завжди запитую тих, хто його використовує: чому ? І ніхто не може відповісти, чому вони цим користуються.

Щоб прямо підвести підсумок, дужки навколо виразів, що повертаються, використовуються людьми, які не зовсім розуміють різницю між функціональними макросами та функціями, або які заплутані щодо переваги оператора або порядку правил оцінки в C. Немає кодування вигода від використання дужок.

Таким чином

return value;

правильніше, ніж

return (value)

тому що останній припускає, що ви не зовсім знаєте, що робите :)


-3

Обидва вони однакові у вашому випадку.


MM, будь ласка, поясніть ваш коментар?
Zeshan Khan

1
якщо aє 5тоді return a++;і return (a++);(що однаково) обоє повернуться5
ММ

2
конкретно, postinc / decrement повертає значення передмодифікації свого операнда, і жодна кількість дужок або інших безрезультатних спроб примусу не змінить цього.
underscore_d
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.