Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/forums/cpp/)
-   -   why do push_back() and direct access work fine in these codes? (http://www.go4expert.com/forums/pushback-direct-access-fine-codes-t14276/)

aortizb 30Sep2008 13:10

why do push_back() and direct access work fine in these codes?
 
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[i][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;
}


oogabooga 30Sep2008 20:34

Re: why do push_back() and direct access work fine in these codes?
 
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


aortizb 30Sep2008 22:20

Re: why do push_back() and direct access work fine in these codes?
 
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.

aortizb 30Sep2008 22:29

Re: why do push_back() and direct access work fine in these codes?
 
Finally, I understood how to use your USE_PUSH. But I still don't understand why direct access work when I used reserve() method.

oogabooga 1Oct2008 00:45

Re: why do push_back() and direct access work fine in these codes?
 
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;
}


aortizb 1Oct2008 03:05

Re: why do push_back() and direct access work fine in these codes?
 
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[i], 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.

aortizb 1Oct2008 03:31

Re: why do push_back() and direct access work fine in these codes?
 
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;
}


xpi0t0s 1Oct2008 14:05

Re: why do push_back() and direct access work fine in these codes?
 
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/s...r/reserve.html
and compare it with http://www.cplusplus.com/reference/s...or/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[i].reserve(length); to mtr[i].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! :-)

aortizb 1Oct2008 22:42

Re: why do push_back() and direct access work fine in these codes?
 
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.


All times are GMT +5.5. The time now is 05:10.