每个循环的 C++ 向量不会遍历引用?
c++ vector for each loop doesn't iterate through references?
昨天我几乎花了一个小时来调试这个东西,从那时起我就无法停止思考 it.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
不是引用,而是元素的新副本?
谢谢
(代码可能有错别字,我写在phone...)
是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){
//...
}
for (auto v : m_vect)
v.push_back(m_default);
在上面的形式中,range-for 循环使用存储在 m_vect
.[=18= 中的项目的 份 (v
) 进行迭代]
如果你想直接对 references 操作 m_vect
中的项目,你应该明确说明,使用 auto&
:
// v references items in m_vect
for (auto& v : m_vect) {
v.push_back(m_default);
}
您可能会发现 this Whosebug answer on using C++11 range-for 有趣。
代码:
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);
}
}
昨天我几乎花了一个小时来调试这个东西,从那时起我就无法停止思考 it.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
不是引用,而是元素的新副本?
谢谢 (代码可能有错别字,我写在phone...)
是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){
//...
}
for (auto v : m_vect) v.push_back(m_default);
在上面的形式中,range-for 循环使用存储在 m_vect
.[=18= 中的项目的 份 (v
) 进行迭代]
如果你想直接对 references 操作 m_vect
中的项目,你应该明确说明,使用 auto&
:
// v references items in m_vect
for (auto& v : m_vect) {
v.push_back(m_default);
}
您可能会发现 this Whosebug answer on using C++11 range-for 有趣。
代码:
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);
}
}