shared_ptr销毁后,其指向对象内的std::vector赋值后能否安全访问?
我有个疑问:如果持有一个包含std::vector的对象的shared_ptr,把这个vector赋值给另一个变量后,当shared_ptr超出作用域销毁,赋值后的vector能不能安全访问?
举个例子:示例代码里inner()函数创建了持有sample_compound_obj对象的shared_ptr,把对象里的vector赋值给引用参数,等shared_ptr销毁后在main()里访问这个vector;实际场景是ROS回调中,把传入的const shared_ptr&消息里的std::vector赋值给全局/成员变量,回调结束shared_ptr销毁后,能不能正常使用这个vector?
代码示例
#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 } }
回答
完全可以安全访问。
原因很简单:std::vector的赋值操作(input = hehe->vektor;)是深拷贝——它会把原vector里的所有元素复制一份到目标vector的独立内存空间中,目标vector拥有这份新内存的完全所有权,和原对象里的vector没有任何关联。
哪怕原对象(由shared_ptr管理的sample_compound_obj)被销毁,原vector的内存被释放,也不会影响已经完成赋值的目标vector——因为它用的是自己的独立内存块。
你的代码运行后会输出:
About to enter outer()... About to enter inner()... About to create sample_compound_obj... I'm alive! About to return from inner()... Goodbye, thank you forever! About to return from outer()... 1 2 3
可以看到原对象已经被销毁(输出了析构函数内容),但main()里的vector依然能正常输出元素,完全没问题。
放到ROS的场景里也是一样的:把消息shared_ptr里的vector赋值给全局/成员变量后,这个变量就拥有了独立的元素拷贝,回调结束消息的shared_ptr销毁,完全不影响你后续使用这个vector。
内容的提问来源于stack exchange,提问作者NaOH

