【问题标题】:c++ vector for each loop doesn't iterate through references?每个循环的 c++ 向量不会遍历引用?
【发布时间】: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)

标签: c++ vector foreach reference pass-by-reference


【解决方案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 StackOverflow 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){
         //...
      }
      

      【讨论】:

        猜你喜欢
        • 2021-06-26
        • 2015-05-21
        • 2012-01-22
        • 2012-09-12
        • 1970-01-01
        • 2015-06-16
        • 1970-01-01
        • 2014-03-26
        • 2016-10-13
        相关资源
        最近更新 更多