What happens if an object resizes its container?

This is not a question of why you write such code, but rather as a question of how the method is executed in relation to the object to which it is attached.

If I have a structure like:

struct F { // some member variables void doSomething(std::vector<F>& vec) { // do some stuff vec.push_back(F()); // do some more stuff } } 

And I use it as follows:

 std::vector<F>(10) vec; vec[0].doSomething(vec); 

What happens if push_back(...) in doSomething(...) causes the vector to expand? This means that vec[0] will be copied and then deleted in the middle of its method execution. It would be nice.

Can someone explain what exactly is going on here?

  • Does the program crash right away? Is the method just trying to work with data that does not exist?
  • Does the method render an orphaned object until it encounters a problem, like a change in the state of an object?

I am wondering how a method call is associated with an associated object.

+8
c ++ memory-management stl
source share
2 answers

Yes this is bad. Maybe your object will be copied (or moved to C ++ 11 if this difference applies to your code) while you are inside doSomething (). Therefore, after push_back () returns, this pointer may no longer point to the location of your object. For the specific case of vector :: push_back (), it is possible that the memory indicated by this was freed, and the data was copied to a new array somewhere else. For other containers (like a list) that leave their items in place, this (probably) will not cause problems at all.

In practice, it is unlikely that your code will crash immediately. Most likely, this is an entry in free memory and silent damage to the state of your object F. You can use tools such as valgrind to detect this behavior.

But basically you have the right idea: do not do this, it is unsafe.

+7
source share

Can someone explain what exactly is going on here?

Yes. If you access the object , after push_back , resize or insert redistributed the contents of vector , this behavior is undefined, which means what actually happens before your compiler, your OS, what do some more stuff is and, possibly, a number of other factors, such like perhaps the phase of the moon, the humidity in some remote place ... you name it; -)

In short, this (indirectly through the implementation of std::vector ) calls the destructor of the object itself, so the object has expired. In addition, the memory previously occupied by the object was freed by the vector allocator. Therefore, the use of object non-static members leads to undefined behavior, because the this pointer passed to the function no longer points to the object. However, you can access the static members of the class:

 struct F { static int i; static int foo(); double d; void bar(); // some member variables void doSomething(std::vector<F>& vec) { vec.push_back(F()); int n = foo(); //OK i += n; //OK std::cout << d << '\n'; //UB - will most likely crash with access violation bar(); //UB - what actually happens depends on the // implementation of bar } } 
+3
source share

All Articles