14

I read a couple of posts on how to return a vector from a method include these ones:

  1. c11 rvalues and move semantics confusion return statement

  2. want speed pass by value

  3. why does visual studio not perform return value optimization rvo

  4. Wiki - Return Value Optimization

and I'm still confused on how to pass a vector the right way in VS2013 and what are the differences between the following methods in this code(the questions are marked in the comments):

class Foo{
 private:
   std::vector<int> vect;

 public:
     //1 - classic way?
    void GetVect(std::vector<int>& v)
      {
         v = vect;// assignment with swap?
      }

    //2 - RVO?
    std::vector<int> GetVect()
      {
        return vect;
      } 

    //3 - RVO with const?
    std::vector<int> GetVect() const
      {
        return vect;
      }

    //4 - just move?
    std::vector<int> GetVect() 
      {
        return std::move(vect);
      }  

     //5 - move with {}?
    std::vector<int> GetVect() 
      {
        return { std::move(vect) };
      }  
 }

So I m not sure if //1 is an explicit form of //2, not sure if 3 works. What are the differences between 4 and 5? How to test it if RVO works for vectors in VS2013?

Community
  • 1
  • 1
CrSe
  • 328
  • 1
  • 2
  • 10
  • 2
    I'm confused. Why are you worried about copy elision and moving when your `GetVect()` implies that it's a getter function? –  Feb 27 '15 at 08:29
  • 2
    Does `Foo` own the vector? Is `GetVec` supposed to give read-only access to the vector? Should it allow to write to the vector? Should it transfer ownership? The answers to those questions are important to design you class correctly. – MadScientist Feb 27 '15 at 08:32
  • 2
    Do you just want to expose the actual `std::vector` or its values? I.e. is it important to you to pass by reference? – Mario Feb 27 '15 at 08:32
  • 4
    Certainly moving is not an "alternative" here. It does something quite different to not moving. – juanchopanza Feb 27 '15 at 08:33
  • @remyabel I don't know if copy elision works in VS2013 for vectors – CrSe Feb 27 '15 at 08:34
  • 3
    What's your intended semantics? – T.C. Feb 27 '15 at 08:34
  • @MadScientist; @Mario yes Foo owns the vector I just need it's values – CrSe Feb 27 '15 at 08:36
  • 1
    Recommend you read "Effective Modern C++" Item 25: Use std::move on rvalue references, std::forward on universal references. Talk about std::move and RVO that may help you – Ron Tang Feb 27 '15 at 09:18

1 Answers1

19
//1 - classic way?
void GetVect(std::vector<int>& v)
  {
     v = vect;// assignment with swap?
  }

This is just plain ugly, you still need a copy and you make your interface too complex.

//2 - RVO?
std::vector<int> GetVect()
  {
    return vect;
  } 

//3 - RVO with const?
std::vector<int> GetVect() const
  {
    return vect;
  }

Functionally the same, but you likely want 3 to indicate that getVect does not change your class state so const semantics can be applied correctly.

//4 - just move?
std::vector<int> GetVect() 
  {
    return std::move(vect);
  }  

It seems very unlikely you want this, after calling GetVect the internal vect will no longer contain any elements.

 //5 - move with {}?
std::vector<int> GetVect() 
  {
    return { std::move(vect) };
  }  

This should end up being the same as 4, you just call the return object's move constructor more explicitly.

For performance what you might actually want is this:

const std::vector<int>& GetVect() const
{
    return vect;
}

This way you can read the object without the need for copying. If you want to write to the returned vector, create a copy explicitly. More details can be found in this question

Community
  • 1
  • 1
KillianDS
  • 16,936
  • 4
  • 61
  • 70
  • To your first answer , I don't think you need a copy. look here https://web.archive.org/web/20130930101140/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value you can just use swap – CrSe Feb 27 '15 at 09:23
  • 1
    The code that you posted is copying. If you'd do a [swap](http://en.cppreference.com/w/cpp/container/vector/swap) the same issues apply as with 4 and 5, your class internal state would be changed. Usually you don't want this for a 'get' function. – KillianDS Feb 27 '15 at 09:40