昨天我几乎花了一个时间来调试这个东西,从那时起我就不能再考虑它.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
引用了一个引用,但是该元素的新副本?
由于 (代码中可能存在拼写错误,我在手机上写了...)
答案 0 :(得分:2)
是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){
//...
}
答案 1 :(得分:2)
for (auto v : m_vect) v.push_back(m_default);
在上面的表单中,range-for循环使用v
中存储的项目的副本(m_vect
)进行迭代。
如果您希望直接对m_vect
中的项目引用进行操作,则应明确使用 auto&
:< / p>
// 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很有趣。
答案 2 :(得分:2)
代码:
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);
}
}