在C ++中的向量中使用push_back vs at

问题描述

在C ++中使用向量有疑问。它与向量中的push_back方法有关。 对于第一个程序,我使用push_back将元素插入向量中。 对于第二个程序,我使用了at()将元素插入向量。

#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

如果我使用myvector.at()插入如下所示的元素,那很好。

#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
$

我使用push_back的方式有什么问题?对,这是将元素插入向量的一种方法

解决方法

此循环中的问题:

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

是,如果您曾经进入循环,即myvector最初并不为空,则每个push_back都会增加向量的大小。由于i在循环中每次都会增加一次,因此它永远不会赶上向量的大小,最终会导致无限循环。


.at()不存在此问题,因为它仅索引向量,而不会更改其大小。只要at的参数为有效索引,就可以毫无问题地访问该职位。

,

问题是您将元素推入永不停止的循环中:

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

第一次迭代后,向量将具有4个元素,而i将是1。在每次迭代中,i增加1,myvector.size()也增加1,条件将永远不会为假。

另一方面,

std::vector::at不会将元素添加到向量中。因此,经过3次迭代后,循环结束。

,

问题出在这一行:

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

您要声明一个包含3个元素的向量。在这种情况下,这些元素是空字符串。

以后再myvector.pushback("hi")时,您将元素添加到向量中。之前的空字符串仍在添加的字符串之前。

要定义一个空向量,只需执行以下操作:

std::vector<string> myvector;

如果您知道要添加3个元素,也可以这样做

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

reserve的目的是预先分配内存。除非您实际插入任何新元素,否则此预先分配的内存将不会成为向量的一部分。

请记住,std::vector的行为不应该像c那样的数组。 std::vector的目的是调整大小,因此您无需预先决定所需的元素数,也无需跟踪其当前使用的大小。

,

push_backvector的末尾添加一个新元素。它增加了大小,并且不提供对现有元素的访问。

at()用于访问vector的元素。它不会增加vector的大小,也不会添加元素。它是对现有元素的读/写。

所以我们不能将两者相互比较。每个人都有不同的工作。

我们可以将operator[]at()进行比较。前者不会抛出范围异常,因为它不会检查,而后者会超出范围并在应有情况时抛出异常。

其他答案完全涵盖了为什么第一个代码挂起的原因,因此在此不再赘述。