Best way to return list of objects in C++?

前端 未结 6 2094
眼角桃花
眼角桃花 2021-02-12 08:56

It\'s been a while since I programmed in C++, and after coming from python, I feel soooo in a straight jacket, ok I\'m not gonna rant.

I have a couple of functions that

相关标签:
6条回答
  • 2021-02-12 09:17

    I'd use the generic approach:

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

    Now you can call it

    std::vector<MagicIngredients> ingredients;
    std::vector<MagicResults> result;
    
    DoMagic(ingredients.begin(), ingredients.end(), std::back_inserter(results));
    

    You can easily change containers used without changing the algorithm used, also it is efficient there's no overhead in returning containers.

    0 讨论(0)
  • 2021-02-12 09:19

    If you really need a new list, I would simply return it. Return value optimization will take care of no needless copies in most cases, and your code stays very clear.
    That being said, taking lists and returning other lists is indeed python programming in C++.

    A, for C++, more suitable paradigm would be to create functions that take a range of iterators and alter the underlying collection.

    e.g.

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

    (with iterator possibly being a template, depending on your needs)

    Chaining operations is then a matter of calling consecutive methods on begin(), end(). If you don't want to alter the input, you'd make a copy yourself first.

    std::vector theOutput(inputVector);
    

    This all comes from the C++ "don't pay for what you don't need" philosophy, you'd only create copies where you actually want to keep the originals.

    0 讨论(0)
  • 2021-02-12 09:19

    Another problem with returning a list of objects (opposed to working on one or two lists in place, as BigSandwich pointed out), is if your objects have complex copy constructors, those will called for each element in the container.

    If you have 1000 objects each referencing a hunk of memory, and they copy that memory on Object a, b; a=b; that's 1000 memcopys for you, just for returning them contained in a container. If you still want to return a container directly, think about pointers in this case.

    0 讨论(0)
  • 2021-02-12 09:29

    If you want to be really hardcore, you could use boost::tuple.

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

    But since it seems all your objects are of a single, non-polymorphic type, then the std::vector is all well and fine. If your types were polymorphic (inherited classes of a base class) then you'd need a vector of pointers, and you'd need to remember to delete all the allocated objects before throwing away your vector.

    0 讨论(0)
  • 2021-02-12 09:32

    Using a std::vector is the preferably way in many situations. Its guaranteed to use consecutive memory and is therefor pleasant for the L1 cache.

    You should be aware of what happends when your return type is std::vector. What happens under the hood is that the std::vector is recursive copied, so if SomeType's copy constructor is expensive the "return statement" may be a lengthy and time consuming operation.

    If you are searching and inserting a lot in your list you could look at std::set to get logarithmic time complexity instead of linear. (std::vectors insert is constant until its capacity is exceeded).

    You are saying that you have many "pipe functions"... sounds like an excellent scenario for std::transform.

    0 讨论(0)
  • 2021-02-12 09:33

    The only thing I can see is that your forcing a copy of the list you return. It would be more efficient to do something like:

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

    Because you pass in the list you want to return, you avoid the extra copy.

    Edit: This is an old reply. If you can use a modern C++ compiler with move semantics, you don't need to worry about this. Of course, this answer still applies if the object you are returning DOES NOT have move semantics.

    0 讨论(0)
提交回复
热议问题