Возврат нескольких значений от функции C++

Я думаю, правильный ответ должен быть java.sql.Timestamp не является специфичным для часового пояса. Временная метка представляет собой составную часть java.util.Date и отдельную наносекунду. В этом классе нет информации о часовом поясе. Таким образом, так же, как Date, этот класс просто содержит миллисекунды с 1 января 1970 года, 00:00:00 GMT + nanos.

В PreparedStatement.setTimestamp (int parameterIndex, Timestamp x, Calendar cal) Календарь используется драйвером для изменения часовой пояс по умолчанию. Но Timestamp по-прежнему занимает миллисекунды в GMT.

API неясно, как именно JDBC-драйвер должен использовать Calendar. Провайдеры, похоже, не знают, как их интерпретировать, например. последний раз, когда я работал с MySQL 5.5 Calendar, драйвер просто игнорировал Calendar как в PreparedStatement.setTimestamp, так и в ResultSet.getTimestamp.

216
задан Fred Larson 26 November 2008 в 15:38
поделиться

13 ответов

Для возврата двух значений я использую std::pair (обычно typedef'd). Необходимо посмотреть boost::tuple (в C++ 11 и более новый, существует std::tuple) больше чем для двух результатов возврата.

С введением структурированной привязки в C++ 17, возвращаясь std::tuple должен, вероятно, стать принятым стандартом.

192
ответ дан SergeyA 4 November 2019 в 13:50
поделиться

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

Возможный пример:

include "boost/tuple/tuple.hpp"

tuple <int,int> divide( int dividend,int divisor ) 

{
  return make_tuple(dividend / divisor,dividend % divisor )
}
1
ответ дан PRAFUL ANAND 4 November 2019 в 13:50
поделиться

Я сказал бы, что нет никакого предпочтительного метода, все это зависит от того, что Вы собираетесь сделать с ответом. Если бы результаты будут используемыми вместе в последующей обработке тогда, структуры имеют смысл, если не я был бы склонен передавать тогда как отдельные ссылки, если функция не была используемой в составном операторе:

x = divide( x, y, z ) + divide( a, b, c );

я часто принимаю решение 'раздать структуры' ссылкой в списке параметров вместо того, чтобы иметь передачу копией наверху возврата новой структуры (но это потеет маленький материал).

void divide(int dividend, int divisor, Answer &ans)

Отсутствуют сбивающие с толку параметры? Параметр, отправленный как ссылка, предполагает, что значение собирается измениться (в противоположность ссылке константы). Разумное именование также удаляет беспорядок.

2
ответ дан Patrick 4 November 2019 в 13:50
поделиться

Альтернативы включают массивы, генераторы , и инверсия управления , но ни один не является соответствующим здесь.

Некоторые (например, Microsoft в историческом Win32) склонны использовать параметры ссылки для простоты, потому что ясно, кто выделяет и как это будет считать стек, уменьшает быстрое увеличение структур и позволяет отдельное возвращаемое значение для успеха.

"Чистые" программисты предпочитают структуру, предполагая, что это значение функции (как имеет место здесь), а не что-то, что это затронуто случайно функцией. Если бы у Вас была более сложная процедура или что-то с состоянием, Вы, вероятно, использовали бы ссылки (предполагающий, что у Вас есть причина того, что не использовался класс).

2
ответ дан Mark 4 November 2019 в 13:50
поделиться

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

3
ответ дан John Dibling 4 November 2019 в 13:50
поделиться

Используйте структуру или класс для возвращаемого значения. Используя std::pair может работать на данный момент, но

  1. это негибко, если Вы решаете позже, что Вы хотите больше возвращенной информации;
  2. не очень ясно из объявления функции в заголовке, что возвращается и в какой порядок.

Возврат структуры с самодокументированием членских имен переменной, вероятно, будет менее склонным к ошибке для любого использующего Вашу функцию. Надев мою шляпу коллеги на мгновение, Ваш divide_result структура легка для меня, потенциального пользователя Вашей функции, сразу понять после 2 секунд. Бездельничание с ouput параметрами или таинственными парами и кортежами заняло бы больше времени для прочтения и может использоваться неправильно. И скорее всего даже после использования функции несколько раз я все еще не буду помнить правильного порядка аргументов.

5
ответ дан DIF 4 November 2019 в 13:50
поделиться

Существует прецедент для возврата структур в C (и следовательно C++) стандарт с div, ldiv (и, в C99, lldiv) функции от <stdlib.h> (или <cstdlib>).

'соединение возвращаемого значения и возвращаемых параметров' является обычно наименее чистым.

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

, Если существует больше чем два возвращаемых значения, то подобный структуре механизм является, вероятно, лучшим.

10
ответ дан Jonathan Leffler 4 November 2019 в 13:50
поделиться

Решение OO для этого состоит в том, чтобы создать класс отношения. Это не взяло бы дополнительного кода (сохранит некоторых), было бы значительно более чистым/более ясным, и даст Вам некоторые дополнительные рефакторинги, позволяющие Вам очищать код вне этого класса также.

На самом деле я думаю, что кто-то рекомендовал возвратить структуру, которая достаточно близка, но скрывает намерение, что это должно быть полностью продуманным классом с конструктором и несколькими методами, на самом деле "метод", который Вы первоначально упомянули (как возврат пары) должен, скорее всего, быть членом этого класса, возвратив экземпляр себя.

я знаю, что Вашим примером был просто "Пример", но факт - то, что, если Ваша функция не делает путь, больше, чем какая-либо функция должны делать, если Вы хотите, чтобы он возвратил несколько значений, Вы почти наверняка пропускаете объект.

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

Другая вещь, которая должна была быть индикатором, что что-то было неправильно: в OO у Вас нет по существу данных - OO не о раздавании данных, класс должен управлять своими собственными данными внутренне, любая передача данных (включая средства доступа) является знаком, что Вы, возможно, должны заново продумать что-то..

12
ответ дан Bill K 4 November 2019 в 13:50
поделиться

Лично, мне обычно не нравятся возвращаемые параметры по ряду причин:

  • это не всегда очевидно в вызове, какие параметры являются ins и который является outs
  • , обычно необходимо создавать локальную переменную для ловли результата, в то время как возвращаемые значения могут использоваться встроенные (который может или не может быть хорошей идеей, но по крайней мере у Вас есть опция)
  • , это кажется инструментом для очистки мне для имения "в двери" и "дверь" в функцию - все исходные данные входят здесь, все выводы прибывают туда
  • , мне нравится сохранять мои списки аргументов максимально короткими

, у меня также есть некоторое резервирование о методе пары/кортежа. Главным образом часто нет никакого естественного порядка к возвращаемым значениям. Как читатель кода, чтобы знать, является ли result.first частным или остатком? И лицо, осуществляющее внедрение могло изменить порядок, который повредит существующий код. Это особенно коварно, если значения являются тем же типом так, чтобы никакая ошибка компилятора или предупреждение не были бы сгенерированы. На самом деле эти аргументы относятся к возвращаемым параметрам также.

Вот другой пример кода, этот немного менее тривиальный:

pair<double,double> calculateResultingVelocity(double windSpeed, double windAzimuth,
                                               double planeAirspeed, double planeCourse);

pair<double,double> result = calculateResultingVelocity(25, 320, 280, 90);
cout << result.first << endl;
cout << result.second << endl;

это печатает groundspeed и курс, или курс и groundspeed? Это не очевидно.

Выдерживают сравнение с этим:

struct Velocity {
    double speed;
    double azimuth;
};
Velocity calculateResultingVelocity(double windSpeed, double windAzimuth,
                                    double planeAirspeed, double planeCourse);

Velocity result = calculateResultingVelocity(25, 320, 280, 90);
cout << result.speed << endl;
cout << result.azimuth << endl;

я думаю, что это более ясно.

, Таким образом, я думаю, моим предпочтительным вариантом в целом является метод структуры. Идея пары/кортежа вероятна отличное решение в определенных случаях. Я хотел бы избежать возвращаемых параметров, если это возможно.

120
ответ дан Fred Larson 4 November 2019 в 13:50
поделиться
std::pair<int, int> divide(int dividend, int divisor)
{
   // :
   return std::make_pair(quotient, remainder);
}

std::pair<int, int> answer = divide(5,2);
 // answer.first == quotient
 // answer.second == remainder

станд.:: пара является по существу Вашим решением для структуры, но уже определенный для Вас и готовый адаптироваться к любым двум типам данных.

23
ответ дан James Curran 4 November 2019 в 13:50
поделиться

Если Ваша функция возвращает значение через ссылку, компилятор не может сохранить его в регистре при вызывании других функций, потому что, теоретически, первая функция может сохранить адрес переменной, переданной ему в глобально доступной переменной, и вызванные функции любого subsecuently могут изменить его, таким образом, компилятор будет иметь (1) сохраняют значение от регистров назад к памяти прежде, чем вызвать другие функции и (2) перечитает его, когда это будет необходимо от памяти снова после любого из таких вызовов.

, Если Вы возвращаетесь ссылкой, оптимизация Вашей программы пострадает

4
ответ дан dmityugov 4 November 2019 в 13:50
поделиться

Это совершенно зависит от фактической функции и значения нескольких значений и их размеров:

  • , Если бы они связаны как в Вашем дробном примере, тогда я пошел бы со структурой или экземпляром класса.
  • , Если они действительно не связаны и не могут быть сгруппированы в класс/структуру тогда, возможно, необходимо осуществить рефакторинг метод в два.
  • В зависимости от размера в оперативной памяти значений Вы возвращаетесь, можно хотеть возвратить указатель на экземпляр класса или структуру, или использовать параметры ссылки.
16
ответ дан Stewart Johnson 4 November 2019 в 13:50
поделиться

Вот полный пример такого вида проблемного решения

#include <bits/stdc++.h>
using namespace std;
pair<int,int> solve(int brr[],int n)
{
    sort(brr,brr+n);

    return {brr[0],brr[n-1]};
}

int main()
{
    int n;
    cin >> n;
    int arr[n];
    for(int i=0; i<n; i++)
    {
        cin >> arr[i];
    }

    pair<int,int> o=solve(arr,n);
    cout << o.first << " " << o.second << endl;

    return 0;
}
-2
ответ дан 23 November 2019 в 04:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: