i'm trying iterate on vector, keeping copy of value previous iteration. surprise, prev
pointer ends pointing @ current value of loop.
#include <iostream> #include <vector> int main() { std::vector<std::string> v; v.push_back("one"); v.push_back("two"); v.push_back("three"); std::string *prev = nullptr; (std::string s : v) { std::cout << "s: " << s << std::endl; if (prev == nullptr) { std::cout << "prev: (null)" << std::endl << std::endl; } else { std::cout << "prev: " << *prev << std::endl << std::endl; } prev = &s; } std::cout << "final prev: " << *prev << std::endl; }
here's output:
s: 1 prev: (null) s: 2 prev: 2 s: 3 prev: 3 final prev: 3
why this? what's right way fix it?
just change
for (std::string s : v) {
to
for (std::string& s : v) {
that way prev = &s;
storing address of actual string inside vector instead of constructing local copy , taking address of local variable.
to elaborate little more:
in original version, s
local std::string
variable gets newly copy constructed in each loop iteration. @ end of loop taking address of local variable destroyed directly after wards, resulting in dangling pointer , undefined behavior, when accessing pointer in next iteration. however, because s
created @ same position in each loop iteration, undefinded behavior realize in form of prev
pointing new local variable s
initialized next element of array. address stored in prev valid in next cycle, pointing fresly created local variable again copy of next element in vector. std::cout << "prev: " << *prev
print same string std::cout << "s: " << s
. compiler optimizations 1 imagine other possible behaviors.
now new variant, s
again local variable, it's not copy reference current element in v. result &s
returns address actual element in vector - , not local variable - content not changed between loop iterations , can use prev
way expected.