0

Recently I tried to implement a simple algorithm in C++ using containers and I ran into a behavior I did not expect and I can not explain. I am new to work with containers so it is possible that the explanation is simple but I just can not see it now.

So, I have a structure to represent a Point that is as simple as:

struct Point{
    double x;
    double y;
    double z;
};

and a simple function for its printing

ostream& operator<<(ostream & os, const Point p){
    os << "x= "<<p.x << " y= "<<p.y << " z= "<<p.z;
    return os;
}

Now, in a certain part of the code, I allocate a vector of Points of certain size and fill it.

vector<Point>* points = new vector<Point>(number_of_lines);

for (int i = 0; i < number_of_lines; i++){
    (*points)[i] = some_data;
}

Later in the code I call

Point* new_point = function_g(points); 
cout<<"Outside the function1 : " << *new_point<<endl;
cout<<"Outside the function2 : " << *new_point<<endl;

where the function_g is defined (somewhat) as:

Point* function_g(vector<Point>* points){
    Point* out;
    int len = points->size();

   for(int j = 0; j<len; j++){
       Point i = points->at(j);
       if (some_condition){
            out = &i;
       }
    }

    cout << "In the function: " << *out<<endl;
    return out;
}

So in this function_g I intend to iterate over the points and find one that fits a condition (I know there is one there) and then I want to return a pointer to the point so I can work with it further in the code. However, when I run the code, I get:

In the function: x= 0.1 y= 0.1 z= 0.1
Outside the function: x= 0.1 y= -8.69944e+32 z= 0.1
Outside the function: x= 4.67894e-310 y= -8.69944e+32 z= 4.94066e-324

so in the function, I get right results when using the pointer, however outside they go wrong and the pointed memory is corrupted. Can anyone explain me, please, what is happening?

Galik
  • 42,526
  • 3
  • 76
  • 100
Adam
  • 11
  • 2
    `Point i = points->at(j);` makes a copy of the item in the vector, then you return the address of that copy. The copy is destroyed when the function ends and accessing that memory is undefined behaviour. – Retired Ninja Apr 18 '21 at 22:06
  • even if it doesn't make a local copy take a pointer of an element in a vector is still not safe because the vector can grow and reallocate the memory – Alessandro Teruzzi Apr 18 '21 at 22:08
  • 1
    @Adam, the style of the code in your example is not what it is recommended in modern C++, the new operator should be seldomly used. In fact, raw pointer in general are not the norm at all – Alessandro Teruzzi Apr 18 '21 at 22:11
  • It is very rare to need to allocate a `std::vector` dynamically. They already store their internal data dynamically. – Galik Apr 18 '21 at 22:12
  • I think it does, thank you! And is there a way to get a pointer onto the vector's element instead of its copy? – Adam Apr 18 '21 at 22:15
  • Of course there is. But as soon as another value gets added to the vector that pointer will no longer be valid, unless some very, very specific steps get taken in advance. – Sam Varshavchik Apr 18 '21 at 22:16
  • It would be better to return the index of the item in the vector. – Retired Ninja Apr 18 '21 at 22:18
  • Keeping a pointer to the element of a `std:::vector` is potentially dangerous. If you change the size of the vector you invalidate any pointers to its elements. – Galik Apr 18 '21 at 22:18
  • [Here](https://stackoverflow.com/a/67073005/15388024) you can see an example code for a reference to a vector element. The reference contains the index and a reference to the vector instead of the memory address. This way the vector can relocate the elements and your reference stays valid. It's in the `ObjectRef` class. – jabaa Apr 18 '21 at 22:22

0 Answers0