Как я могу получить второе значение из функции с помощью указателя *? - PullRequest
2 голосов
/ 17 июня 2020

У меня есть функция, и мне нужно получить от нее два значения. Функция может возвращать только одно значение. Я где-то читал, что могу использовать указатель для получения второго значения, когда я пытаюсь это сделать, я получаю сообщение об ошибке, поэтому похоже, что значение указателя не может go за пределами зоны видимости. Это означает, что у меня есть только одно значение. Как я могу получить второе значение из функции с помощью указателя?

Ответы [ 3 ]

1 голос
/ 17 июня 2020

Идея, которую вы где-то читали, заключается в том, что код, который вызывает функцию, создает объект, передает указатель на объект в качестве аргумента функции, а функция назначает объект, косвенно перебирая указатель.

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

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

struct Point {
    double x;
    double y;
};

Point example()
{
    // until C++20
    return {
        42.,
        1337.,
    };
    // since C++20
    return {
        .x = 42.,
        .y = 1337.,
    };
}

Здесь мы вернули два значения в одном объекте.

1 голос
/ 17 июня 2020

Экземпляр определенного типа - «одно значение». Рассмотрим этот класс:

struct foo {
     int bar;
     double moo;
};

Теперь я могу написать функцию, которая возвращает одно значение этого типа:

foo asdf() { 
    foo result;
    result.bar = 42;
    result.moo = 3.14159;
    return result;
}

PS: Не используйте указатели. Можно использовать так называемые исходящие параметры, но если вы это сделаете, вам следует использовать ссылку вместо указателя:

void asdf2(int& bar,int& moo) {
     bar = 42;
     moo = 3.14159;
}

Вызовите так:

int x = 0;
double y = 0.;
asdf2(x,y);

Однако, Параметры out не очень хороши, потому что в foo f = asdf(); более очевидно, что возвращается из функции, по сравнению с asdf2(x,y).

0 голосов
/ 17 июня 2020

Есть как минимум три подхода.

Первый, как вы уже упомянули, - это вернуть значение с использованием параметра типа указателя.

Например,

#include <iostream>

int minmax( int x, int y, int *max )
{
    int min = x;
    *max = y;

    if ( y < x )
    {
        min = y;
        *max = x;
    }

    return min; 
}

int main() 
{
    int min, max;

    min = minmax( 20, 10, &max );

    std::cout << "min = " << min << ", max = " << max << '\n';
}

Результат программы:

min = 10, max = 20

Здесь в программе переменная max передается по ссылке в терминах C.

Второй подход - это передача по ссылке в терминах C ++. Например,

#include <iostream>

int minmax( int x, int y, int &max )
{
    int min = x;
    max = y;

    if ( y < x )
    {
        min = y;
        max = x;
    }

    return min; 
}

int main() 
{
    int min, max;

    min = minmax( 20, 10, max );

    std::cout << "min = " << min << ", max = " << max << '\n';
}

Вывод программы такой же, как показано выше.

И вы действительно можете вернуть один объект, но составного типа, который содержит другие подобъекты. Например,

#include <iostream>
#include <utility>

std::pair<int, int> minmax( int x, int y )
{
    return y < x ? std::pair<int, int>( y, x ) : std::pair<int, int>( x, y );
}

int main() 
{
    auto p = minmax( 20, 10 );

    std::cout << "min = " << p.first << ", max = " << p.second << '\n';
}

Вывод программы такой же, как показано для первой демонстрационной программы.

Вместо стандартного шаблона класса std :: pair, который имеет два члена данных, вы можете использовать шаблон класса std::tuple, если вы хотите вернуть более двух объектов. Или вы можете написать свой собственный составной тип (шаблон или не шаблон) в виде структуры или класса.

Например

#include <iostream>
#include <tuple>

std::tuple<int, int, int> get_sorted( int x, int y, int z )
{
    if ( not ( y < x ) && not ( z < x ) )
    {
        return not ( z < y ) ? std::make_tuple( x, y, z )
                             : std::make_tuple( x, z, y );
    }
    else if ( not ( z < y ) )
    {
        return not ( z < x ) ? std::make_tuple( y, x, z )
                             : std::make_tuple( y, z, x );
    }
    else
    {
        return not ( y < x ) ? std::make_tuple( z, x, y )
                             : std::make_tuple( z, y, x );
    }
}

int main() 
{
    auto t = get_sorted( 15, 10, 20 );

    std::cout << "( " << std::get<0>( t ) 
              << ", " << std::get<1>( t )
              << ", " << std::get<2>( t )
              << " )\n";
}

Вывод программы:

( 10, 15, 20 )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...