C++中的vector for each循环不能遍历引用吗?

3

昨天我花了将近一个小时来调试这个东西,从那以后,我就一直在想它。C

我试图实现一个带有字符串索引的2D矩阵...

class CSqrMatrix(){
  ....
  void insert(string str){
     bool b = map.insert(str,m_size).second;
     if (b){
         m_size++;
         vector<int> ve;
         for (int i = 0; i < m_vect.size(); i++) 
             ve.push_back(m_default);
         m_vect.push_back(ve);
         for (auto v : m_vect)
             v.push_back(m_default);
     }
  ...
map<string,int> map;
vector < vector<int> > m_vect;
int m_default;
int m_size;
};

在进行了一些插入操作后,当我尝试访问一个元素时,如下所示:

m_vect[0][0] = 8;

我遇到了无效的写入和段错误...并且m_vect[0].size()的值为0; 我尝试了一切,最终当我将for each循环改为普通循环时,问题得到了解决。

for (int i = 0; i < m_vect.size(); i++){
     m_vect[i].push_back(m_default);

程序工作良好...

这意味着,v 不是一个引用,而是元素的一个新副本吗?

谢谢 (代码中可能会有拼写错误,我是在手机上写的...)


2
没错。如果你想要一个引用,可以尝试使用 for (auto& v : m_vect) - n. m.
3个回答

5
for (auto v : m_vect)
    v.push_back(m_default);
在上面的表格中,范围for循环使用m_vect中存储的项目的副本v)进行迭代。
如果您想直接操作m_vect中项目的引用,则应该明确指出,使用auto&
// v references items in m_vect
for (auto& v : m_vect) {
    v.push_back(m_default);
}

你可能会发现这篇关于使用C++11范围for循环的StackOverflow答案很有趣。

4
是的,v 确实是一个副本。你应该这样做:
for (auto& v : m_vect){
   v.push_back(m_default);
}

请记住,std::vector的复制是针对容器及其中所有项的深度复制,这是一项非常昂贵的操作。因此,即使不进行编辑,如果您想通过一个向量的向量(std::vector<std::vector<T>>)传递,您应该通过引用传递(如果您不希望进行编辑,则需要使用const):

for(/*const*/ auto& v:vectors){
   //...
}

4

代码:

for (auto v : m_vect)
    v.push_back(m_default);

等价于以下内容 (请参阅C++标准[stmt.ranged]):

{
    auto && __range = (m_vect);
    for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin)
    {
        auto v = *__begin;      // <-- new copy in each iteration
        v.push_back(m_default); // add item to the copy
                                // the copy goes out of scope
    }
}

所以,是的,v 不是一个引用,而是在每次迭代中创建一个新副本?

你想要的是:

for (auto& v : m_vect)
    v.push_back(m_default);

这相当于:

{
    auto && __range = (m_vect);
    for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin)
    {
        auto& v = *__begin; // <-- new reference in each iteration
        v.push_back(m_default);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接