why do push_back() and direct access work fine in these codes?

Discussion in 'C++' started by aortizb, Sep 30, 2008.

  1. aortizb

    aortizb New Member

    Joined:
    Sep 12, 2008
    Messages:
    32
    Likes Received:
    0
    Trophy Points:
    0
    Hello, could someone explain me why this two codes work? I got surprised when I found out that I can use either push_back() method or direct access mtr[j] when mtr was declared as: vector< vector<double> > mtr;

    which of the codes would be the most efficient?

    code 1:
    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
      int length = 5;
      int num = 10;
      
      vector< vector<int> > mtr;
      
      mtr.resize(length);
      for(int i = 0; i < length; i++)
      {
        mtr[i].reserve(length);
    
        for (int j = 0; j < length; j++)
        {
          mtr[i][j] = num;
          cout<<"mtr["<<i<< "]["<< j<< "]= "<< mtr[i][j] <<endl;
        }
      }  
        
      return 0;
    }
    
    code 2:
    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
      int length = 5;
      int num = 10;
      
      vector< vector<int> > mtr;
      
      mtr.resize(length);
      for(int i = 0; i < length; i++)
      {
        mtr[i].reserve(length);
    
        for (int j = 0; j < length; j++)
        {
          mtr[i].push_back(num);
          cout<<"mtr["<<i<< "]["<< j<< "]= "<< mtr[i][j] <<endl;
        }
      }  
        
      return 0;
    }
    
     
  2. oogabooga

    oogabooga New Member

    Joined:
    Jan 9, 2008
    Messages:
    115
    Likes Received:
    11
    Trophy Points:
    0
    The direct access works because you've reserved the space,
    and it is faster since it does not involve a function call,
    unless perhaps push_back is inlined.
    For such similar programs it's better to use an #ifdef:
    Code:
    #define USE_PUSH  true   // at top of program
    
    //         . . .
    
    #ifdef USE_PUSH
        mtr[i].push_back(num);
    #else
        mtr[i][j] = num;
    #endif
     
  3. aortizb

    aortizb New Member

    Joined:
    Sep 12, 2008
    Messages:
    32
    Likes Received:
    0
    Trophy Points:
    0
    thanks for your reply. I don't understand how your #define USE_PUSH works. Another thing, my question is precisely because reserve() method does not allow direct access since reserve() is a bunch of addresses and not numbers. You need to fill the array first in order to directly access into it. But I don't understand why in the code 1 above it is working. If I do the following:

    Code:
    vector<double> vec;
    vec.reserve(5);
    
    for (i = 0 ; i < 5; i++)
       vec[i] = 10;
    
    will not work.
     
  4. aortizb

    aortizb New Member

    Joined:
    Sep 12, 2008
    Messages:
    32
    Likes Received:
    0
    Trophy Points:
    0
    Finally, I understood how to use your USE_PUSH. But I still don't understand why direct access work when I used reserve() method.
     
  5. oogabooga

    oogabooga New Member

    Joined:
    Jan 9, 2008
    Messages:
    115
    Likes Received:
    11
    Trophy Points:
    0
    The code works fine for me.
    reserve() sets the "capacity" of the vector to at least size.
    capacity() returns the number of elements that the vector can
    hold before it needs to allocate more space.
    As for using preprocessor #define's, I should have said #if instead of #ifdef. It's demonstrated in the code below.
    Code:
    #include <vector>
    #include <iostream>
    using namespace std;
    
    #define USE_PAUSE true
    #define SIZE 5
    
    int main()
    {
        vector<double> vec;
        vec.reserve( SIZE );
    
        cout << "Room for: " << vec.capacity() << endl;
        for( int i = 0 ; i < SIZE; ++i )  vec[i] = i;
        for( int i = 0 ; i < SIZE; ++i )  cout << vec[i] << ' ';
        cout << endl;
    
    #if USE_PAUSE
        system( "pause" );
    #endif
        return 0;
    }
     
    shabbir likes this.
  6. aortizb

    aortizb New Member

    Joined:
    Sep 12, 2008
    Messages:
    32
    Likes Received:
    0
    Trophy Points:
    0
    Thanks for your reply. I found the answer to the problem. In brief is in using reserve() and then access with [] whould work for such types like int and double. But it is an inconsistent use of it because even entering numbers in the way vec, a simple check to the size of the element vec.size() after the elements has been entered will return 0. That is why is inconsistent, so it should be avoided.

    On considering the above, I would like to know an alternative method which is efficient to do the same.
     
  7. aortizb

    aortizb New Member

    Joined:
    Sep 12, 2008
    Messages:
    32
    Likes Received:
    0
    Trophy Points:
    0
    For your reference. Try this code and you will experiment such inconsistencies.

    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
      int length = 5;
      int num = 10;
      
      vector< vector<int> > mtr;
      
      mtr.resize(length);
      for(int i = 0; i < length; i++)
      {
        mtr[i].reserve(length);
    
        for (int j = 0; j < length; j++)
        {
       //   mtr[i][j] = num;
          cout<<"mtr["<<i<< "]["<< j<< "]= "<< mtr[i][j] <<endl;
        }
    
        cout << "SIZE: " << mtr[i].size() << endl;
      }  
        
      return 0;
    }
    
     
  8. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    What compiler are you using? I think this is possibly a quirk in the implementation of your STL vector class. In Visual Studio 2005 vector<int> mtr; mtr.reserve(5); mtr[2]=7; throws "vector subscript out of range"; I'd suggest that your implementation of STL could have a bug in this regard.

    I noticed in the last bit of code that you use mtr.resize() rather than mtr.reserve().
    See http://www.cplusplus.com/reference/stl/vector/reserve.html
    and compare it with http://www.cplusplus.com/reference/stl/vector/resize.html
    There's no indication in the reserve() doc that this actually creates new elements. The VS2005 code above throws no exceptions if I change reserve() to resize().

    Also changing mtr.reserve(length); to mtr.resize(length); in your last code means the code throws no exceptions.

    So the "inconsistency" is that resize() doesn't do the same as reserve(). RTFM! :)
     
  9. aortizb

    aortizb New Member

    Joined:
    Sep 12, 2008
    Messages:
    32
    Likes Received:
    0
    Trophy Points:
    0
    I am using GNU compiler under redhat enterprise linux 9.0.

    First of all I didn't use resize in my last part of the code, I used SIZE to show that if I use [] after using reserve() procedure SIZE will not notice that there is some elements in the array. And that is because reserve() is thought to delacre that some memory is going to be used but reserve() does not fill the array for you, you should do it using push_back() method. Because int, double, etc are build-in type using [] actually will work but size(), at() and I guess iterators will not realize about the change, so you will not be able to use size() and iterators in your loop later on. That is the inconsistency. On the other hand, if you use resize() that will allocate the memory and fill the array for you with default numbers of the type you are using (int, double, etc). So, finally, the safest way to do is use resize() in all the loops, as follows:
    Code:
      ....
      mtr.resize(length);
      for(int i = 0; i < length; i++)
      {
        mtr[i].resize(length);
        ....
      }  
      .....
    
    So, Same as you, I had troubles using reserve an directly accessing using []. That was I told in my previous post to the other user that gave some comments. But he told me that in his compiler is working well.
     
    Last edited: Oct 1, 2008

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice