3

I found out the nice tool provided by std::reference_wrapper, but this behaviour sounds weird to me.

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <vector>
#include <numeric>
int main()
{
    std::vector<int> vectorA(10);
    std::vector<std::reference_wrapper<int>> vec;
    std::iota(vectorA.begin(),vectorA.end(),0);

    for(auto i: vectorA){
        std::cout << "In vectorA: "<<  i << " ";
    }
    std::cout << "\n";

    for(unsigned i=0; i< vectorA.size(); i++){
        vec.push_back(std::ref(vectorA[i]));
    }

    for(auto i: vec){
        std::cout << "In vec: "<<  i << " ";
    }
    std::cout << "\n";

    vectorA.erase(vectorA.begin()+9);

    for(auto i: vectorA){
        std::cout << "In vectorA: "<<  i << " ";
    }
    std::cout << "\n";


    for(auto i: vec){
        std::cout << "In vec: "<<  i << " ";
    }
    std::cout << "\n";

}

Why erasing an element referenced in vec (vectorA[9]) does not affect the size of vector vec? Furthermore, why does the vec[9] still be accessible?

Luca Jungla
  • 150
  • 8
  • 2
    `this behaviour sounds weird to me` This behaviour is undefined. :) C++ doesn't protect against stupid things. – DeiDei Jan 24 '20 at 11:43
  • Because it's your resposibility to make sure referenced object out-live the reference. You would get the same behaviour with pointers or normal references. It's just how `c++` works. It doesn't do things magically for you without you asking it to. – super Jan 24 '20 at 11:43

1 Answers1

3

std::reference_wrapper stores a reference to an object. It does not affect the lifetime of the referenced object in any way, and you are committing that you will not try and use the std::reference_wrapper after the referenced object has been destroyed. The penalty for doing so is undefined behaviour.

Thus, when you erase the referenced element from vectorA, the reference wrapper in vec is now invalid, but it doesn't know, and you cannot tell. Any use of that reference wrapper object will now cause undefined behaviour.

One possible consequence of undefined behaviour is that your program continues to run, and that is what happens here. You try and use the invalid reference wrapper object, and you get a value back, but that does not mean the program is valid.

Anthony Williams
  • 66,628
  • 14
  • 133
  • 155