每个循环的 C++ 向量不遍历引用?

c++ vector for each loop doesn't iterate through references?

本文关键字:遍历 引用 向量 C++ 循环      更新时间:2023-10-16

昨天我花了将近一个时间来调试这个东西,从那时起我就无法停止思考它。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 (int i = 0; i < m_vect.size(); i++){
     m_vect[i].push_back(m_default);

该计划运行良好...

那么这是否意味着,v不是引用,而是元素的新副本?

谢谢(代码中可能有错别字,我在电话里写的...

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

在上述形式中,范围循环使用存储在m_vect中的项目的副本v)进行迭代。

如果你想直接对m_vect中的项目的引用进行操作,你应该明确这一点,使用 auto&

// v references items in m_vect
for (auto& v : m_vect) {
    v.push_back(m_default);
}

您可能会发现这个 StackOverflow 答案在使用 C++11 范围很有趣。

代码:

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);
    }
}

是的v确实是一个副本。你应该这样做:

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

请记住,std::vector副本是容器和所有项目的深层副本,这确实是一项昂贵的操作。因此,如果你想在不编辑的情况下传递向量(std::vector<std::vector<T>>),你应该通过ref传递(如果你不想编辑,则用const):

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