Имеют ли значение круглые скобки вокруг результата в операторе возврата?


79

Есть ли разница между этими двумя операторами внутри функции?

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

и это?

bool returnValue = true;
// Code
return returnValue;

Первое заключено в круглые скобки returnValue.


Спасибо, Роб, вы успешно уловили суть вопроса. В Essence мне было интересно, сделал ли компилятор что-то особенное (например, попытался сначала оценить выражение) или просто проигнорировал его.
Jose Villalta

1
На этот вопрос сложно ответить ни при какомc++ / c. Было бы хорошо уточнить определение языка, но я не знаю, как это исправить 9 лет спустя.
Йонас Штайн

Ибо 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возвращается значение, intа во втором func1- значение int&. Разница в семантике напрямую связана с окружающими круглыми скобками .

Спецификатор autoв его последней форме был введен в C ++ 11. В спецификации языка C ++ это описывается как:

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

Также в C ++ 11 появился decltypeспецификатор, описанный в спецификации языка C ++ :

Проверяет объявленный тип объекта или запрашивает возвращаемый тип выражения.

[вырезать]

  1. Если аргумент является либо именем объекта / функции без скобок, либо выражением доступа к члену (object.member или pointer-> member), то decltype указывает объявленный тип сущности, указанной этим выражением.

  2. Если аргумент - любое другое выражение типа T, то

    а) если категория значения выражения - xvalue, то decltype указывает T &&

    б) если категория значений выражения lvalue, то decltype указывает T &

    c) в противном случае 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 var1;это фактически то же самое, что и возврат типа decltype(var1)( intвозвращаемый тип по правилу 1 выше), а во втором случае return (var1);фактически то же самое, что и decltype((var1))( int &возвращаемый тип по правилу 2b).

Скобки делают возвращаемый тип int&вместо int, таким образом изменяя семантику. Мораль истории - «Не все круглые скобки в возвращаемом типе одинаковы».


Оператор return без скобок по-прежнему является выражением lvalue, верно? Если в этом сценарии он не рассматривается как значение x. Можете ли вы объяснить ценностную категорию доходности без скобок?
void.pointer

1
Оператор return возвращает чтение введенного в него выражения, т. Е. Захватывает r-значение из содержащегося в нем выражения и возвращает его. Мы никогда не возвращаем lvalue. Возможно, что в каком-то компиляторе есть ошибка, соответствующая описанию, которое вы здесь приводите, и по причинам, которые вы здесь указываете, но это никогда не должно быть return (x);эквивалентным случаю return &x;и не должно быть возможным, чтобы это привело к возврату значение x, но со ссылкой на тип x.
Теодор Мердок

4
Вау, какая отвратительная языковая конструкция. Просто совершенно ... непрозрачно. Хорошая рецензия, спасибо.
Пол Сандерс

5
C ++ - чрезвычайно интересный язык. Но такие скрытые "особенности" иногда сводят меня с ума ...
andreee 04

Наш код полон ненужных скобок. Мы тоже используем 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
@John: фактически игнорируется. :)
Джеймс

3
+1… это единственный ответ, который утверждает, что скобки на самом деле излишни, и показывает, что их использование немного глупо.
Конрад Рудольф

4

AFAIK, нет ничего другого.

В C ++ выражения могут иметь форму: exprили (expr). Итак, последнее - это выражение с большим количеством типов. Чтобы узнать больше об этом, обратитесь к грамматике (ищите «выражение»).


Дэвид, спасибо за ссылку. У меня есть грамматика из книги Страуструпа по C ++, но (я полагаю, из-за лени) я не смотрю на нее так много, теперь, когда она добавлена ​​в закладки в моем браузере, я могу обращаться к ней чаще.
Jose Villalta


3

Я предполагаю, booчто это опечатка, и вы спрашиваете, есть ли разница между

return expr;

и

return(expr);

Ответ - нет.


2

Нет разницы!!

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

Кстати return, это утверждение, а не функция.


2

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


1
... но этого никогда не происходит. С чего бы это? Что трудно прочитать о выражении без скобок? Мне кажется, что добавление скобок - это беспорядок. Что касается ясности, люди думают, что returnэто жадный оператор, который return m * x + cможет вернуть mи отбросить остальные, или что?
underscore_d

1

Вы чрезмерно замедляете работу компилятора!

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


С семантической точки зрения? Они абсолютно идентичны. Независимо от того, есть ли круглые скобки, returnоператор полностью оценит выражение перед его возвратом.


5
Я думаю именно так. Заставляя компилятор выполнять ненужную работу по разбору бесполезного беспорядка, он приближается к тепловой смерти Вселенной без уважительной причины.
Максим Егорушкин

4
Как вы относитесь к биткойнам?
Джереми Николай

0

Они одинаковые. Я довольно часто вижу синтаксис скобок и всегда спрашиваю тех, кто его использует: почему ? И никто не может ответить, зачем они его используют.

Короче говоря, круглые скобки вокруг возвращаемых выражений используются людьми, которые не совсем понимают разницу между функционально-подобными макросами и функциями или которые не понимают приоритета операторов или порядка правил оценки в C. Нет кодирования стиль выигрывает от использования скобок.

Таким образом

return value;

правильнее чем

return (value)

потому что последнее предполагает, что вы не совсем понимаете, что делаете :)


-3

Оба варианта одинаковы в вашем случае.


ММ, не могли бы вы объяснить свой комментарий?
Зешан Хан

1
если aесть 5то return a++;и return (a++);(что одно и то же) оба вернутся5
MM

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