Форум программистов, компьютерный форум, киберфорум
Kerry_Jr
Войти
Регистрация
Восстановить пароль
Рейтинг: 5.00. Голосов: 1.

Оператор return и запятая в С++

Запись от Kerry_Jr размещена 06.08.2015 в 17:10

Как мной уже не раз было замечено, новички при написании функций нередко пытаются вернуть из неё несколько значений сразу, как то, например:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
int func(int a, int b)
{
    int c = a + b;
    int d = a * b;
 
    return c, d;
}
int main()
{
    std::cout << func(3, 4) << std::endl;
}
Например, в языке Python такая конструкция прошла бы на "ура", т.к. в нем поддерживается составной оператор присваивания
Python
1
2
3
4
5
6
7
8
def func (a, b):
    c = a + b
    d = a * b
    return c, d
 
e, f = func(3, 4)
print e #выведет 7
print f #выведет 12
Давайте разберёмся в подобной ситуации на С++.
Запомните: оператор return возвращает одно и только одно значение из функции в точку её вызова (за исключением ситуации, когда тип возвращаемого значения функции - void).
Что же происходит в данном случае: прежде чем вернуть значение, return вычисляет значение своего операнда (если это выражение, как в нашем случае). Таким образом, мы плавно переходим к оператору "запятая".
Оператор "запятая" сначала вычисляет свой левый операнд, а затем правый и возвращает правый операнд, который в свою очередь будет передан return'у. А return приведёт значение операнда к типу возвращаемого значения функции (если таковое приведение возможно или если оно нужно) и вернёт его вызывающей стороне.
Теперь при компиляции данной программы с уровнем предупреждений Wall Visual C++ не выдаст предупреждений, а MinGW сообщит
Код:
main.cpp:8:12: warning: left operand of comma operator has no effect [-Wunused-value]
Компилятор предупреждает, что левый операнд запятой не имеет эффекта, его значение не используется.
А при запуске вывод будет таким
Код:
12
Что и требовалось доказать.

Резюме:
1. Как я писал выше, опреатор return возвращает из функции всегда только одно значение.
2. Если Вы все ещё считаете иначе, не удивляйтесь тому, что из всех, переданных return'у через запятую, параметров return вернёт вызывающей стороне значение последнего.
Размещено в Без категории
Просмотров 2929 Комментарии 6
Всего комментариев 6
Комментарии
  1. Старый комментарий
    Аватар для Avazart
    Куда хуже:
    C++
    1
    2
    3
    4
    
    A* pa= new A;
    B* pb= new B;
    // ...
    delete pa,pb;   //  pb не удалится

    Не по теме:

    Я кстати так лажал ...

    Запись от Avazart размещена 06.08.2015 в 18:52 Avazart на форуме
    Обновил(-а) Avazart 06.08.2015 в 18:54
  2. Старый комментарий
    [quote]Например, в языке Python такая конструкция прошла бы на "ура", т.к. в нем поддерживается составной оператор присваивания[/quote]
    Не только в Python, во многих ЯП.

    F#:
    [FSHARP]let func a b = a + b , a * b
    let a, b = func 3 4
    printfn "%i %i" a b[/FSHARP]

    [url]https://dotnetfiddle.net/FxrYg1[/url]
    Запись от Ev_Hyper размещена 06.08.2015 в 19:28 Ev_Hyper вне форума
  3. Старый комментарий
    Аватар для Avazart
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    #include <tuple>  //   > C++11
     
    std::tuple<int,int> func(int a, int b)
    {
        int c = a + b;
        int d = a * b;
     
        // return {c,d}; // > C++17
        return std::make_tuple(c,d);
    }
     
    int main()
    {
       int c=0, d=0;
     
       std::tie(c,d)= func(5,10);
     
       std::cout<< c << std::endl;
       std::cout<< d << std::endl;
     
        return 0;
    }
    Запись от Avazart размещена 07.08.2015 в 12:45 Avazart на форуме
    Обновил(-а) Avazart 07.08.2015 в 12:47
  4. Старый комментарий
    до C++11(да и сейчас) для этого использовали
    C++
    1
    
    std::pair<>
    .
    Запись от S_el размещена 07.08.2015 в 13:19 S_el вне форума
  5. Старый комментарий
    Go:
    [JAVA]package main

    import "fmt"

    func f(x, y int) (int, int) {
    return x+y, x*y
    }
    func main() {
    x, y := f(3,4)
    fmt.Println(x)
    fmt.Println(y)
    }[/JAVA]


    [url]https://play.golang.org/p/juqlkIzOgB[/url]
    Запись от Ev_Hyper размещена 07.08.2015 в 13:27 Ev_Hyper вне форума
  6. Старый комментарий
    Аватар для Avazart
    S_el, обычно используют передачу по ссылке/указателю вместо возврата значения, а все что выше как бы сахар.

    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    void func(int a, int b, int& c, int& d)
    {
        c = a + b;
        d = a * b;
    } 
     
    int main()
    {
       int c=0, d=0;
     
       func(5,10,c,d);
     
       std::cout<< c << std::endl;
       std::cout<< d << std::endl;
    }
    Если один из результатов может не использоваться можно передавать по указателю что позволит передавать нулевой указатель для такой ситуации.

    Параметры можно оформлять в структуры.
    Запись от Avazart размещена 08.08.2015 в 00:30 Avazart на форуме
    Обновил(-а) Avazart 08.08.2015 в 00:35
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.