badri
badri

Reputation: 627

Using push_back vs at in a vector in C++

Have a doubt in using vectors in C++. it is to do with the push_back method in the vector. For the first program, i have used push_back to insert elements into the vector. For the second program, i have used at( ) to insert elements into the vector.

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main ()
{
  std::vector<string> myvector (3);

  cout << "In main" << endl;
  for (unsigned i=0; i<myvector.size(); i++)
  {
    myvector.push_back("hi");  //Note: using push_back here.
  }
  cout << "elements inserted into myvector" << endl;

  std::cout << "myvector contains:" << endl;
  for (auto v: myvector)
     cout << v << endl;

  // access 2nd element
  cout << "second element is " << myvector[1] << endl;

  return 0;
}
Output:    
Hangs after entering main.    
$ ./a.out    
In main

whereas if I used myvector.at() to insert the elements like below, its fine.

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main ()
{
  std::vector<string> myvector (3);

  cout << "In main" << endl;
  for (unsigned i=0; i<myvector.size(); i++)
  {
    myvector.at(i) = "hi";  // using 'at' instead of 'push_back'
  }
  cout << "elements inserted into myvector" << endl;

  std::cout << "myvector contains:" << endl;
  for (auto v: myvector)
     cout << v << endl;

  // access 2nd element
  cout << "second element is " << myvector[1] << endl;

  return 0;
}

Output:
./a.out
In main
elements inserted into myvector
myvector contains:
hi
hi
hi
second element is hi
$

What is wrong with the way i have used push_back ? This is one of the ways we insert elements into the vector, right.

Upvotes: 1

Views: 3789

Answers (4)

Iman Rosstin
Iman Rosstin

Reputation: 2355

push_back adds a new element at the end of a vector. It increases the size and does not provide access to existing elements.

at() is to access an element of a vector. It does not increase the size of vector and does not add an element to it. it is to read/write of an existing element.

So we can not compare these two with each other. Each does a different job.

We can however compare operator[] with at(). The former does not throw out a range exception, cause it does not check, while the latter check out of bound and throws an exception when it should.

Other answers fully covered why the first code hangs so I am not repeating them here.

Upvotes: 1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122476

The problem is that you push the elements in a loop that never stops:

for (unsigned i=0; i<myvector.size(); i++)
{
   myvector.push_back("hi");  //Note: using push_back here.
}

After the first iteration the vector will have 4 elements and i will be 1. As you increment i by one in each iteration and myvector.size() also increases by one, the condition will never be false.

std::vector::at on the other hand, does not add elements to the vector. Hence, after 3 iterations the loop ends.

Upvotes: 5

HAL9000
HAL9000

Reputation: 2188

The problem is in this line:

std::vector<string> myvector (3);

You are declaring a vector with 3 elements. In this case, those elements are empty strings.

When you later do myvector.pushback("hi") You add elements to your vector. The previous empty string are still there in in front of your added string.

To define an empty vector, you just do:

std::vector<string> myvector;

and if you know you are going to add 3 elements you can also do

std::vector<string> myvector;
myvector.reserve(3);

The purpose of reserve is to preallocate memory. This preallocated memory will not be part of your vector until you actually insert any new elements.

Remember that std::vector is not supposed to behave like c-like arrays. The purpose of std::vector is to be resizable, so you don't need to decide up front how many elements you need, or keep track of its current used size.

Upvotes: 2

cigien
cigien

Reputation: 60238

The issue in this loop:

for (unsigned i=0; i<myvector.size(); i++)
{
    myvector.push_back("hi");  //Note: using push_back here.
}

is that if you ever enter the loop, i.e. myvector is not initially empty, then each push_back will increase the size of the vector. Since i is incremented once each time in the loop, it will never catch up to the size of the vector, and you end up with an infinite loop.


.at() doesn't have this problem, since it only indexes into the vector, without ever changing its size. So long as the argument to at is a valid index, you can access this position without any issues.

Upvotes: 8

Related Questions