无法在2D矩阵中设置值(矢量矢量)

时间:2018-01-27 06:33:20

标签: c++ vector iterator

我无法理解为什么我无法在2D矩阵(向量矢量)中设置值。如果我使用C风格的循环或迭代器它可以工作,但如果我使用基于c ++范围的循环它不起作用。有人可以解释一下原因吗?

感谢。

struct my_str {
   int value;

   my_str(int v) : value(v) {}
};

int main(int argc, char *argv[])
{
   // Initialise with some dummy data (creates a 3 x 2 matrix)
   vector<vector<my_str>> array2D;
   for (int i=0; i<3; ++i) {
      vector<my_str> tmp;
      for (int j=0; j<2; ++j)
         tmp.push_back( my_str(-999) );
      array2D.push_back(tmp);
   }

   // Now try to replace the values
   int ctr=0;

   // Fails
   for (auto array1D: array2D)
      for (auto it: array1D)
         it.value = (float)++ctr;

   // Fails
   for (auto array1D: array2D)
      for (std::vector<my_str>::iterator it=array1D.begin(); it != array1D.end() ;++it)
         (*it).value = (float)++ctr;

   // Fails
   for (int i=0; i<array2D.size(); i++)
      for (auto array1D: array2D[i])
         array1D.value = (float)++ctr;

   // Works
   for (std::vector<std::vector<my_str>>::iterator array1D=array2D.begin(); array1D != array2D.end() ;++array1D)
      for (std::vector<my_str>::iterator it=array1D->begin(); it != array1D->end() ;++it)
         (*it).value = (float)++ctr;

   // Works
   for (int i=0; i<array2D.size(); i++)
      for (std::vector<my_str>::iterator it=(array2D[i]).begin(); it != (array2D[i]).end() ;++it)
         it->value = (float)++ctr;

   // Works
   for (int i=0; i<array2D.size(); i++)
      for (int j=0; j<(array2D[i]).size(); j++)
         array2D[i][j].value = (float)++ctr;

2 个答案:

答案 0 :(得分:4)

使用引用,否则您将获得副本。

for (auto & array1D: array2D)
          ^
    for (auto & it: array1D)
              ^

auto不会在类型扣除中保留const或引用:

int i{0};
const int ci{0};
int & ri = i;
int const & cri = i;
auto a = i;   // int deduced
auto b = ci;  // int deduced
auto c = ri;  // int deduced
auto d = cri; // int deduced

并且在所有情况下,abcd都是ici的副本。对这些值的任何修改都不会影响ici的值。而

auto & e = i; // int & deduced
e = 1; // i is modified

此处适用于您的for-range循环。

答案 1 :(得分:1)

默认情况下auto推断出表达式的value类型。在基于for循环的范围中,这对于类类型来说是个坏消息,因为每个元素都是容器中原始元素的副本

鉴于

for (auto array1D : array2D)

编译器填写空白 -

for (vector<my_str> array1D : array2D)

为什么要使用副本?幕后的According to the standardarray1D看起来像这样。

std::vector<my_str>::iterator it = array2D.begin();

// this for loop advances the iterator
for (...)
{
    // this is a copy of the element!
    vector<my_str> array1D = *it;
}

这个“失败”工作,因为当你为第二个for循环中的元素赋值时,你将分配给一个复制的向量。这不会修改array2D中的原始元素。

为避免使用副本,请让编译器知道您希望array1D成为array2D内元素的引用。

for (auto &array1D : array2D)