yesterday I spent almost an our while debugging this thing and since then I can't stop thinking about it.C
I tried to implement a 2D matrix with string indexes...
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;
};
after some insertions, when I tried to reach an element like
m_vect[0][0] = 8;
I got an invalid write and segfault... and the value of m_vect[0].size()
was 0; I tried everything, when finally I changed the for each loop to a normal one like
for (int i = 0; i < m_vect.size(); i++){
m_vect[i].push_back(m_default);
the program worked well...
So does that mean, that v
ins't a referecne, but a new copy of the element?
Thanks (there might be typos in the code, I wrote it on the phone...)
Yes v
is indeed a copy. You should do it like this:
for (auto& v : m_vect){
v.push_back(m_default);
}
And keep in mind that std::vector
copy is a deep copy for the container and for all items which is really an expensive operation. So if you want to pass through a vector of vectors ( std::vector<std::vector<T>>
) even without editing, you should pass by ref (with const
if you do not want editing):
for(/*const*/ auto& v:vectors){
//...
}
for (auto v : m_vect) v.push_back(m_default);
In the above form, the range-for loop iterates using copies ( v
) of the items stored in m_vect
.
If you want to operate directly on references to the items in m_vect
, you should be explicit about that, using auto&
:
// v references items in m_vect
for (auto& v : m_vect) {
v.push_back(m_default);
}
You may find this StackOverflow answer on using C++11 range-for interesting.
The code:
for (auto v : m_vect)
v.push_back(m_default);
is equivalent to following ( see C++ standard [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
}
}
So, yes, v
ins't a referecne, but a new copy in each iteration?
What you want is:
for (auto& v : m_vect)
v.push_back(m_default);
That is equivalent to:
{
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);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.