3

Sorry for my English.

Some class:

class Kid {
public:
    ...
    string _name;
    std::list<string> _cuteKids;
};

Use class:

    std::list<Kid> kids;
    kids.push_back(new Kid("Jeck"));
    kids.push_back(new Kid("Anna"));
    kids.push_back(new Kid("Toma"));

    for(auto e: kids) {

         e._cuteKids.push_back("Jeck"); // Many some names...
         [1]
    }
    [2]

If you look at the code in the debugger, the list in paragraph 1 _cuteKids - have item. But if look at the list in paragraph 2 _cuteKids - no have item. Why?

This is just an example, actually I much complicated algorithm, but the bottom line is that after a loop _cuteKids becomes empty. As if it is a static variable (e: kids), not a pointer to a variable of kids.

Tipok
  • 675
  • 8
  • 26
  • Why does a `Kid` contain a list of "cute kids"? A kid is a kid. One kid doesn't contain other kids. This make no sense. You also have a problem with levels of indirection. Given `std::list kids;`, `kids.push_back(new kid("xxx");` can't compile--`new` gives a pointer but you're trying to insert that pointer as the object to which it refers. – Jerry Coffin Sep 16 '14 at 14:44
  • It's strange that you have `std::list kids;` and then you add new `kid`s using **`new`**: `kids.push_back(new Kid("Jeck"));`... – Mr.C64 Sep 16 '14 at 14:47
  • _cuteKids - is a list of children who love child this. The job, it does not change the. – Tipok Sep 16 '14 at 15:38

2 Answers2

4

e is a copy of the list items, so changes to it do not affect the items in the list.

To do what you want, make e a reference:

for (auto &e : kids)
interjay
  • 107,303
  • 21
  • 270
  • 254
1

In your code:

for (auto e: kids) {
    e._cuteKids.push_back("Jeck"); // Many some names...
}

you are doing copies of each item in the kids container, while iterating the container itself, because you missed a "simple" &.

So, the statement e._cuteKids.push_back(...); is operating on a copy, not on the original item. This local copy "evaporates" after each loop iteration, and the original items in the kids container are unaffected.

You have to properly iterate using references (&) to the original items, to avoid these local deep copies:

for (auto& e : kids) {
    // ... do something on 'e' ...
}

Note that there is a proposal for terse range-based for loops (N3994), that may be part of the next iteration of the language (C++17?), to avoid bugs like those in your code:

Range-Based For-Loops: The Next Generation (Revision 1)

Using this newly proposed syntax, it can be possible to simply write:

for (e : kids) {
    // ... do something on 'e' ...
}

without introducing subtle bugs like forgetting the &.

Mr.C64
  • 41,637
  • 14
  • 86
  • 162