PDA

View Full Version : Why changed values in a foreach don't save?



cit
25th July 2014, 23:30
I don't belive in my eyes. I wrote a foreach to change a bool value... (bool FileEntry.selected)



int i=-1;
foreach (FileEntry itmFile, fileList)
{
i++;
if((tmpType=="alle")||(itmFile.type==tmpType)) //Stimmt Typ?
{
if(itmFile.size+currentSize<maxSize) //Begrenzung noch nicht überschritten?
{
currentSize += itmFile.size;
//itmFile.selected=true; //wird ausgewählt
fileList[i].selected=true;
continue;
}
}
//itmFile.selected=false; //wird nicht ausgewählt
fileList[i].selected=false;
}


..and the (now) commted entries like "itmFile.selected=true" change the value only for/in the foreach! After the foreach is done, the value is false, like before. But when i use something like "fileList[i].selected=true", the value is after leaving the foreach is still 'true'. Is that normal???


thx.cit

stampede
25th July 2014, 23:41
This is quite confusing piece of code. You are using "for-each" type of loop, but you are accessing the iterated list via index at the same time. This is not self-explanatory and I strongly recommend not to write such code.
Either just use simple "for (int i=0...)" type of loop, or stick to iterator-based foreach.
// edit: I guess you did that only for tests, so forget above comment


"itmFile.selected=true" change the value only for/in the foreach
Of course it is, since "itmFile" is a copy of the value from list:

foreach (FileEntry itmFile, fileList)
On each iteration you assign a copy from "fileList", roughly it is equivalent to


for (...){
FileEntry itmFile = fileList[i];
}

If you want to iterate and change a sequence via foreach loop, use references:


// change to itmFile will affect objects from fileList
foreach (FileEntry & itmFile, fileList)

cit
26th July 2014, 00:25
Yes, i do this (stupid) iteration-stuff only for testing ;-)

Thanks, you give me the solution. Sorry i normaly work with C#. At C# it's not a "copy". okay, i will do it by ref, because i like the 'foreach' ;-)

PS: what a stumbling block!!!!

Added after 26 minutes:

I tried the "&", but i got an error.



// int i=-1;
foreach (FileEntry & itmFile, fileList)
{
//i++;
if((tmpType=="alle")||(itmFile.type==tmpType)) //Stimmt Typ?
{
if(itmFile.size+currentSize<maxSize) //Begrenzung noch nicht überschritten?
{
currentSize += itmFile.size;
itmFile.selected=true; //wird ausgewählt
//fileList[i].selected=true;
continue;
}
}
itmFile.selected=false; //wird nicht ausgewählt
//fileList[i].selected=false;
}


/usr/include/qt5/QtCore/qglobal.h:860: error: invalid initialization of reference of type 'FileEntry&' from expression of type 'const FileEntry'
for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;}))


For your information:


QList<FileEntry> fileList;

(no pointer)

stampede
26th July 2014, 08:43
Of course, sorry, my bad, I'm just used to C++11 style "for" loops:


for (FileEntry & itmFile : fileList){
//...
}

I forgot the fact that Qt "foreach" makes a copy of the container before entering the loop (but it is cheap thanks to implicit sharing).
Above "for" loop will work as expected.
In order to use it you need to have
1) a compiler that supports c++11 features
2) if not enabled by default, you need to add this to the <project>.pro file:


// .pro
CONFIG += c++11

Here is a small example:


#include <QList>
#include <QDebug>

struct data_t{
int value;
data_t(int a=0) : value(a){}
};

QDebug& operator<< (QDebug& stream, const data_t& d){
stream << d.value;
return stream;
}


int main(){
QList<data_t> list;
list << data_t(1) << data_t(2) << data_t(3);
qDebug() << list;
for (data_t& d : list){
d.value += 1;
}
qDebug() << list;
return 0;
}

// should output:
// 1, 2, 3)
//(2, 3, 4)


Sorry for the confusion.