Search code examples
c++shared-ptrrosstdvector

Using std::vector from an object referenced by shared_ptr after shared_ptr's destruction


I apologise if the title is different from what I will be describing, I don't quite know how to describe it apart from using examples.

Suppose I have a shared_ptr of an object, and within that object, is a vector. I assign that vector to a variable so I can access it later on, and the shared_ptr gets destroyed as it goes out of scope. Question, is the vector I saved "safe" to access?

In the example below, from main(), outer() is called, and within outer(), inner() is called. inner() creates a shared_ptr to an object that contains a std::vector, and assigns it to a variable passed by reference. The role of outer() is to create some form of seperation, so that we know that the shared_ptr is destroyed. In main(), this referenced variable is accessed, but is it safe to use this variable?

#include <iostream>
#include <vector>
#include <memory>

struct sample_compound_obj {
    std::vector<int> vektor;
    sample_compound_obj(){std::cout << "I'm alive!"  << std::endl;};
    ~sample_compound_obj(){std::cout << "Goodbye, thank you forever!"  << std::endl;};
};

bool inner(std::vector<int>& input) {
    std::cout << "About to create sample_compound_obj..."  << std::endl;
    std::shared_ptr<sample_compound_obj> hehe(new sample_compound_obj);

    hehe->vektor.push_back(1);
    hehe->vektor.push_back(2);
    hehe->vektor.push_back(3);

    input = hehe->vektor;
    std::cout << "About to return from inner()..."  << std::endl;
    return true;
}

bool outer(std::vector<int>& input) {
    std::cout << "About to enter inner()..."  << std::endl;
    
    inner(input);

    std::cout << "About to return from outer()..."  << std::endl;

    return true;
}

int main() {
    std::cout << "About to enter outer()..."  << std::endl;
    std::vector<int> vector_to_populate;

    outer(vector_to_populate);

    for (std::vector<int>::iterator it = vector_to_populate.begin(); it != vector_to_populate.end(); it++) {
        std::cout << *it <<std::endl; // <-- is it even "safe" to access this vector
    }
}

https://godbolt.org/z/47EWfPGK3

To avoid XY problem, I first thought of this issue when I was writing some ROS code, where a subscriber callback passes by reference the incoming message as a const shared_ptr&, and the message contains a std::vector. In this callback, the std::vector is assigned (via =) to a global/member variable, to be used some time later, after the end of the callback, so presumably the original shared_ptr is destroyed. One big difference is that in my example, I passed the std::vector by reference between the functions, instead of a global variable, but I hope it does not alter the behavior. Question is, is the std::vector I have "saved", suitable to be used?


Solution

  • is it safe to use this variable?

    Yes, in the below statement, you copy the whole vector using the std::vector::operator= overload doing copy assignment. The two vectors do not share anything and live their separate lives and can be used independently of each other.

    input = hehe->vektor;