Лучший способ возвратить список объектов в C++?

Он работает как быстрыми 3, так и 4

    @IBAction func NextView(_ sender: UIButton) {
        let newVC = self.storyboard?.instantiateViewControllerWithIdentifier(withIdentifier: "NewVC") as! NewViewController

                let transition = CATransition()
                transition.duration = 0.5
                transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
                transition.type = kCATransitionPush
                transition.subtype = kCAGravityLeft
    //instead "kCAGravityLeft" try with different transition subtypes

        self.navigationController?.view.layer.add(transition, forKey: kCATransition)
        self.navigationController?.pushViewController(newVC, animated: false)

            }
21
задан mmcdole 5 February 2009 в 07:36
поделиться

7 ответов

Единственная вещь, которую я вижу, состоит в том, что Ваше принуждение копии списка Вы возвращаетесь. Было бы более эффективно сделать что-то как:

  void DoSomething(const std::vector<SomeType>& in, std::vector<SomeType>& out)
  {
  ...
  // no need to return anything, just modify out
  }

, поскольку Вы передаете в списке, который Вы хотите возвратить, Вы избегаете дополнительной копии.

Редактирование: Это - старый ответ. Если можно использовать современный компилятор C++ с семантикой перемещения, Вы не должны волноваться об этом. Конечно, этот ответ все еще применяется, если объект, который Вы возвращаете, НЕ имеет семантики перемещения.

16
ответ дан 29 November 2019 в 20:59
поделиться

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

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

, например,

void DoSomething(iterator const & from, iterator const & to);

(с итератором, возможно являющимся шаблоном, в зависимости от Ваших потребностей)

, операции Объединения в цепочку являются затем вопросом обращения к последовательным методам, начинаются (), конец (). Если бы Вы не хотите изменять вход, Вы сделали бы копию сами сначала.

std::vector theOutput(inputVector);

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

13
ответ дан 29 November 2019 в 20:59
поделиться

Я использовал бы универсальный подход:

template <typename InIt, typename OutIt>
void DoMagic(InIt first, InIt last, OutIt out)
{
  for(; first != last; ++first) {
    if(IsCorrectIngredient(*first)) {
      *out = DoMoreMagic(*first);
      ++out;
    }
  }
}

Теперь можно назвать его

std::vector<MagicIngredients> ingredients;
std::vector<MagicResults> result;

DoMagic(ingredients.begin(), ingredients.end(), std::back_inserter(results));

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

4
ответ дан 29 November 2019 в 20:59
поделиться

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

tuple<int, int, double> add_multiply_divide(int a, int b) {
  return make_tuple(a+b, a*b, double(a)/double(b));
}

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

1
ответ дан 29 November 2019 в 20:59
поделиться

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

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

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

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

1
ответ дан 29 November 2019 в 20:59
поделиться

Другая проблема с возвратом списка объектов (настроенный против работы над одним или двумя списками на месте, как BigSandwich указал), состоит в том, если Ваши объекты будут иметь конструкторов копии комплекса, то они будут, призвал к каждому элементу в контейнере.

, Если у Вас есть 1 000 объектов каждая ссылка на ломоть памяти, и они копируют ту память на Объекте a, b; a=b; это - 1000 memcopys для Вас, только для возврата их содержавшийся в контейнере. Если Вы все еще хотите возвратить контейнер непосредственно, думайте об указателях в этом случае.

0
ответ дан 29 November 2019 в 20:59
поделиться

Это работает очень простое.

list<int> foo(void)
{
    list<int> l; 
    // do something
    return l;
}

Теперь получающие данные:

list<int> lst=foo();

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

Другой метод, более портативный:

list<int> lst;
// do anything you want with list
lst.swap(foo());

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

Это - эффективный способ сделать задание.

0
ответ дан 29 November 2019 в 20:59
поделиться
Другие вопросы по тегам:

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