0

Today i was playing around with some standard Library functions.. and found this weird output from std::transform() and std::back_inserter whenever the container am using(in this case vector) has more than 2 elements in it.I don't understand this kind of behavior can anyone there help me...

#include<iostream>  
#include<algorithm>  
#include<vector>  
using namespace std;  

/* this version of change works fine for me when i store the incoming value into a   
   static variable  
int change(int n){  
 static int m=n;
 return m * m;  
}*/  

int change(int n){  
return n*n;  
}  

int main(){  
 vector<int> v2(3,3),  
            v1;  

 transform(v2.begin(),v2.end(),back_inserter(v2),change);  

 for(auto v: v2)  
  {   
    cout << v <<"  ";  // prints out a strange random 5th value in v2.  

  }  
 return 0;  
}  
Naseef Chowdhury
  • 2,357
  • 3
  • 28
  • 52
  • 2
    You generally aren't allowed to modify a container or invalidate iterators during the execution of an algorithm when that container is used as an input to the algorithm. – Jared Hoberock Aug 01 '14 at 00:38
  • See http://stackoverflow.com/questions/19200528/is-it-safe-for-the-input-iterator-and-output-iterator-in-stdtransform-to-be-fr – uesp Aug 01 '14 at 00:40
  • possible duplicate of [Iterator invalidation rules](http://stackoverflow.com/questions/6438086/iterator-invalidation-rules) – Deduplicator Aug 01 '14 at 00:44
  • Please avoid long lines in code-blocks. Not everyone looks at these pages with maximized browsers on desktops featuring extra-wide monitors. – Deduplicator Aug 01 '14 at 00:47
  • @JaredHoberock thanks but why is it only the 5th element – The-null-Pointer- Aug 01 '14 at 00:48
  • @user3104126 Your code has undefined behavior, so it's pointless to speculate why you're observing a particular behavior. – Praetorian Aug 01 '14 at 00:49
  • 1
    BTW: [UB has a time-machine](https://stackoverflow.com/q/24527401), so due to the program encountering it on any possible execution, the program has undefined behavior right from the start. – Deduplicator Aug 01 '14 at 00:53
  • @user3104126 probably a wizard did it – Jared Hoberock Aug 01 '14 at 00:54

1 Answers1

2

The most likely cause is that the storage for the vector is being reallocated when you push_back elements into it (that's what assigning to the back_insert_iterator results in). This invalidates the begin and end iterators passed to transform, and subsequent assignments result in undefined behavior.

Your problem can be solved if you reserve() enough room in the vector before the call to transform

vector<int> v2(3,3);

v2.reserve(v2.size() * 2);
transform(v2.begin(),v2.end(),back_inserter(v2),change);

This produces the desired output.

3 3 3 9 9 9

Live demo

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • thanks that worked....but the function works when i store the value of the incoming iterator into a static variable and return it.. – The-null-Pointer- Aug 01 '14 at 01:29
  • 2
    @user3104126 It's still undefined behavior because `transform` is dereferencing invalid iterators once the `vector` resizes for the first time. It appears to work because by making `m` `static` within `change`, you initialize it *once* with the argument passed to `change` the very first time, and then keep returning the square of that value. So you're never using the invalid values being passed to `change` after the first call. Try adding `v2[0] = 1;` to the `static` version, and you'll see that all the new elements being added are `1`, and do not depend on the remaining `vector` elements. – Praetorian Aug 01 '14 at 02:09
  • thanks very much... well well on point am not using the invalid values passed to the function... thanks once again. – The-null-Pointer- Aug 02 '14 at 06:11