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

Posted

技术标签:

【中文标题】每个循环的 c++ 向量不会遍历引用?【英文标题】:c++ vector for each loop doesn't iterate through references? 【发布时间】:2016-07-09 02:54:00 【问题描述】:

昨天我花了几乎我们的时间来调试这个东西,从那以后我就无法停止思考它。C

我尝试用字符串索引实现二维矩阵...

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 不是引用,而是元素的新副本?

谢谢 (代码可能有错别字,我在手机上写的……)

【问题讨论】:

是的,没错。如果您需要参考,请尝试for (auto&amp; v : m_vect) 【参考方案1】:

代码:

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

【讨论】:

【参考方案2】:
for (auto v : m_vect)
    v.push_back(m_default);

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

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

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

你可能会觉得this *** answer on using C++11 range-for很有趣。

【讨论】:

【参考方案3】:

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

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

请记住,std::vector 副本是容器和所有项目的深层副本,这确实是一项昂贵的操作。所以如果你想通过一个向量的向量(std::vector&lt;std::vector&lt;T&gt;&gt;),即使不编辑,你应该通过 ref(如果你不想编辑,使用const):

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

【讨论】:

以上是关于每个循环的 c++ 向量不会遍历引用?的主要内容,如果未能解决你的问题,请参考以下文章

是否使用指针或引用来访问向量,然后遍历它缓存不友好?

在 C++ 向量的每个元素上调用函数

C++:遍历向量的向量

C++:遍历地图

在 C++ 类中引用向量

C++入门篇之引用,内联函数,auto和范围遍历