Функция возвращающая несколько значений c

Функция возвращающая несколько значений c

Есть ли предпочтительный способ вернуть несколько значений из функции C ++? Например, представьте функцию, которая делит два целых числа и возвращает как частное, так и остаток. Один из способов, которые я обычно вижу, это использование опорных параметров:

Вариант состоит в том, чтобы вернуть одно значение и передать другое через опорный параметр:

Другим способом было бы объявить структуру, содержащую все результаты, и вернуть следующее:

Является ли один из этих способов вообще предпочтительным, или есть другие предложения?

Изменить: в реальном коде может быть более двух результатов. Они также могут быть разных типов.

Решение

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

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

Другие решения

В C ++ 11 вы можете:

или со структурами:

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

  • при вызове не всегда очевидно, какие параметры являются входными, а какие выходными.
  • Обычно вам нужно создать локальную переменную, чтобы перехватить результат, в то время как возвращаемые значения могут использоваться встроенными (что может быть или не быть хорошей идеей, но, по крайней мере, у вас есть опция)
  • мне кажется чище иметь функцию «в дверях» и «вне дверей» — все входы входят сюда, все выходы выходят туда
  • Мне нравится, чтобы мои списки аргументов были как можно короче

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

Вот еще один пример кода, этот чуть менее тривиален:

Имеет ли этот отпечаток скорость и курс или курс и скорость? Это не очевидно.

Сравните с этим:

Я думаю, что это понятнее.

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

std :: pair — это, по сути, ваше структурное решение, но оно уже определено для вас и готово для адаптации к любым двум типам данных.

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

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

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

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

Я знаю, что ваш пример был просто «Примером», но факт в том, что если ваша функция не выполняет больше, чем любая другая функция, если вы хотите, чтобы она возвращала несколько значений, вы почти наверняка пропускаете объект.

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

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

С C ++ 17 вы также можете вернуть одно или более неподвижных / не копируемых значений. (в некоторых случаях). Возможность возврата неподвижных типов обеспечивается за счет новой оптимизации гарантированного возвращаемого значения, которая хорошо сочетается с сводные показатели, и что можно назвать шаблонные конструкторы.

Хорошая вещь об этом, что это гарантированно не вызывает любой копирование или перемещение. Вы можете сделать пример many структура variadic тоже. Больше деталей:

Существует прецедент для возврата структур в стандарте C (и, следовательно, C ++) с div , ldiv (а в С99 lldiv ) функции от (или же ).

«Сочетание возвращаемого значения и возвращаемых параметров» обычно наименее чистое.

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

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

прочитал C++ версия этого вопроса но на самом деле не понимал этого.

может кто-нибудь, пожалуйста, объяснить ясно, если это можно сделать и как?

25 ответов

кортежи с двумя значениями имеют Item1 и Item2 свойства.

теперь, когда c# 7 был выпущен, вы можете использовать новый синтаксис включенных кортежей

который можно было бы использовать следующим образом:

вы также можете предоставить имена своим элементам (поэтому они не являются "Item1", "Item2" и т. д.). Вы можете сделать это, добавив имя в подпись или методы возврата:

Читайте также:  Как передать данные с самсунга на самсунг

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

проверить этой ссылке чтобы увидеть больше примеров того, что можно сделать 🙂

вы можете использовать три разных способа

1. номер модели / ref / out параметры

использование ref:

С помощью:

2. struct / class

использование struct:

использование класса:

3. Кортеж!—10—>

Кортеж класс!—10—>

Кортежи C# 7

вы не можете сделать это в C#. Что вы можете сделать, это иметь out parameter или верните свой собственный класс (или struct, если вы хотите, чтобы он был неизменяемым).

С помощью параметра Использование пользовательского класса (или структуры)

Если вы имеете в виду возврат нескольких значений, вы можете либо вернуть класс/структуру, содержащую значения, которые вы хотите вернуть, либо использовать ключевое слово "out" для ваших параметров, например:

предыдущий постер прав. Невозможно вернуть несколько значений из метода C#. Тем не менее, у вас есть несколько вариантов:

  • возвращает структуру, содержащую несколько элементов
  • возврат экземпляра класса
  • использовать выходные параметры (с помощью out или ref ключевые слова)
  • используйте словарь или пару ключ-значение в качестве вывода

плюсы и минусы здесь часто трудно выяснить. Если вы возвращаете структуру, убедитесь, что она небольшая, потому что структуры являются типом значения и передаются в стек. Если вы возвращаете экземпляр класса, здесь есть некоторые шаблоны проектирования, которые вы можете использовать, чтобы избежать проблем — члены классов могут быть изменены, потому что C# передает объекты по ссылке (у вас нет ByVal, как вы сделали в VB).

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

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

вы либо вернуть экземпляр класса или использовать из параметры. Вот пример параметров:

назовем это так:

есть несколько способов сделать это. Вы можете использовать ref параметры:

при этом передается ссылка на функцию, тем самым позволяя функции изменять объект в стеке вызывающего кода. Хотя это технически не "возвращаемое" значение, это способ заставить функцию делать что-то подобное. В коде выше функция будет возвращать int и (потенциально) изменить bar .

другой аналогичный подход заключается в использовании out параметр. Ан out параметр идентичен параметру ref параметр с дополнительным, принудительным правилом компилятора. Это правило заключается в том, что если вы передадите out параметр в функцию, эта функция должна установить свое значение до возвращения. Кроме этого правила, an

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

тем временем, есть два варианта.

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

Это выглядит так:

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

нет, вы не можете возвращать несколько значений из функции в C# (для версий ниже C# 7), по крайней мере, не так, как вы можете это сделать в Python.

тем не менее, есть несколько альтернатив:

вы можете вернуть массив типа object с несколькими значениями, которые вы хотите в нем.

можно использовать out параметры.

В C#7 есть новый Tuple синтаксис:

вы можете вернуть эту запись:

вы также можете использовать новый синтаксис разрушитель:

будьте осторожны с сериализацией, однако, все это синтаксический сахар — в фактическом скомпилированном коде это будет Tupel (as за принятый ответ) С Item1 и Item2 вместо foo и bar . Это означает, что сериализация (или десериализация) вместо этого будут использоваться эти имена свойств.

Итак, для сериализации объявите класс записи и верните его вместо этого.

также новым в C#7 является улучшенный синтаксис для out параметры. Теперь вы можете объявить out inline, который лучше подходит в некоторых контекстах:

однако в основном вы будете использовать это в собственных библиотеках .NET, а не в собственных функциях.

вы можете попробовать этот "KeyValuePair"

выход :

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

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

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

в основном существуют два метода. 1. Использовать параметры out / ref 2. Возвращает массив объектов

вот основные Two методы:

1) Использование ‘ out в качестве параметра Вы можете использовать " out " как для 4.0, так и для младших версий.

пример ‘out’:

выход:

площадь прямоугольника 20

периметр прямоугольника 18

*Примечание:*о out -ключевое слово описывает параметры, фактические местоположения переменных скопировано в стек вызываемого метода, где эти же расположения могут быть переписаны. Это означает, что вызывающий метод получит доступ к измененному параметру.

Читайте также:  Подключиться к домашней группе вин 10

2) Tuple

пример кортежа:

возврат нескольких значений типа данных с помощью Tuple

выход

Примечание: использование кортежа допустимо из Framework 4.0 и выше. Tuple тип class . Он будет выделен в отдельном расположении на управляемой куче в памяти. После создания Tuple , вы не можете изменить значения его fields . Это делает Tuple еще как struct .

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

вызывающие объекты предоставляют лямбда (или именованную функцию), а intellisense помогает, копируя имена переменных из делегата.

просто используйте в ООП-манере такой класс:

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

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

Я ввел это решение также В вопрос C++, на который ссылается OP.

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

KeyValuePair самый быстрый путь.

из на втором.

кортежа!—6—> самая медленная.

в любом случае, это зависит от того, что лучше для вашего сценария.

вы можете использовать динамический объект. Я думаю, что он имеет лучшую читаемость, чем Кортеж.

способы сделать это:

1) KeyValuePair (самое лучшее представление-0.32 ns):

2) Кортеж — 5.40 НС:

3) из (1.64 НС) или Реф 4) Создайте свой собственный класс/структуру struct

будущая версия C# будет включать именованные кортежи. Посмотрите на эту сессию channel9 для демонстрации https://channel9.msdn.com/Events/Build/2016/B889

пропустить до 13: 00 для кортежа. Это позволит такие вещи, как:

есть предпочтительный способ вернуть несколько значений из функции C++? Например, представьте себе функцию, которая делит два числа и возвращает частное и остаток. Один из способов, который я обычно вижу, это использовать ссылочные параметры:

вариация должна возвращать одно значение и передавать другое через ссылочный параметр:

другим способом было бы объявить структуру, содержащую все результаты и возвращаемую что:

является ли один из этих способов обычно предпочтительным, или есть другие предложения?

Edit: в реальном коде может быть более двух результатов. Они также могут быть разных типов.

18 ответов:

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

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

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

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

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

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

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

сравнить с этим:

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

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

В C++11 вы можете:

std:: pair-это, по сути, ваше структурное решение, но уже определенное для вас и готовое адаптироваться к любым двум типам данных.

это полностью зависит от фактической функции и значения нескольких значений, а также их размеров:

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

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

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

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

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

Читайте также:  Лили морто фото в купальнике

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

С помощью C++17 вы также можете вернуть одно или несколько неподвижных / непересекающихся значений (в некоторых случаях). Возможность возврата неподвижных типов приходит через новую оптимизацию гарантированного возвращаемого значения, и она прекрасно сочетается с Сростки, а что можно назвать шаблонных конструкторов.

прелесть в том, что это гарантированно не вызовет любой копирование или перемещение. Вы можете сделать пример many struct variadic тоже. Более детально:

существует прецедент для возврата структур в стандарте C (и, следовательно, C++) с помощью div , ldiv (и, в C99, lldiv ) функции (или ).

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

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

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

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

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

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

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

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

здесь, я пишу программу, которая возвращает несколько значений(более двух значений) в C++. Эта программа выполняется в c++14 (G++4.9.2). программа похожа на калькулятор.

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

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

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

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

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

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

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

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

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

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

вместо того, чтобы возвращать несколько значений, просто верните одно из них и сделайте ссылку на другие в требуемой функции, например:

почему вы настаиваете на функции с несколькими возвращаемыми значениями? С помощью ООП вы можете использовать класс, предлагающий обычную функцию с одним возвращаемым значением и любое количество дополнительных "возвращаемых значений", как показано ниже. Преимущество заключается в том, что у вызывающего абонента есть выбор, глядя на дополнительные элементы данных, но не требуется для этого. Это предпочтительный метод для сложных вызовов базы данных или сети, где может потребоваться много дополнительной информации о возврате в случае возникновения ошибок.

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

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

мы можем объявить функцию таким образом, что она возвращает переменную типа структуры, определенную пользователем, или указатель на нее . И по свойству структуры мы знаем, что структура в C может содержать несколько значений асимметричных типов (т. е. одна переменная int, четыре переменные char, две переменные float и т. д.)

Ссылка на основную публикацию
Фото на зеленом фоне хромакей
Зеленый фон или «хромакей» применяют при съемках для последующей его замены на любой другой. Хромакей может быть и другого цвета,...
Файловая система для операционной системы windows
Вы знаете, что Windows Phone использует NTFS? Почему большинство карт памяти и почти все USB-накопители по-прежнему используют старый-добрый FAT? Почему...
Файлы в карантине что с ними делать
содержит все нейтрализованные вредоносные программы в корзине в течение определенного периода времени до того момента, как применит к ним соответствующие...
Фото на скайп для пацанов
Крутые фотографии пацанов на аву: фото без лица, в маске анонима, крутые пацаны с битами и с пистолетами. Крутые фото...
Adblock detector