我无法理解为什么我无法在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;
答案 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
并且在所有情况下,a
,b
,c
和d
都是i
和ci
的副本。对这些值的任何修改都不会影响i
或ci
的值。而
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 standard,array1D
看起来像这样。
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)