return 成员变量 shared_ptr 是否安全
Is it safe to return a member variable which is a shared_ptr
假设我有以下代码,这是我的问题的简化示例:
#include <string>
#include <iostream>
#include <memory>
class A{
public:
std::string name() { return "class A"; }
};
class B{
public:
B(){
m_a = std::make_shared<A>();
}
std::shared_ptr<A> get_a() { return m_a; }
private:
std::shared_ptr<A> m_a;
};
std::shared_ptr<A> foo()
{
B b;
return b.get_a();
}
int main()
{
auto a = foo();
auto name = a->name();
std::cout << name;
return 1;
}
我想知道这样做安全吗? "b" 是 B 的实例,将在函数 foo 结束时释放。 main函数中的"a"是B::m_a的shared_ptr。在 "b" 发布后使用 "a" 是否安全?
非常感谢!
那个foo
shared_ptr<A> foo()
{
B b;
return b.get_a();
}
不是 return 对 b 成员的引用,而是该成员的独立副本(副本的副本,如果未进行 RV 优化);和 shared_ptr
a
auto a = foo();
将 A 堆实例从破坏中保存到范围结束。
因此我认为这是安全的,B 们虽然是创作者,但毕竟只是他们创作和发布的许多共享资产的一个用户。
换句话说——最后一个关灯的,而不是开灯的那个。
很安全。
shared_ptr
在堆上创建一个跟踪变量。这使得对象 B
更加复杂,因为即使它是在堆栈上创建的,它也会从堆中分配一个 A
。可能会影响性能。
当跟踪数据的所有用户都停止访问它时,shared_ptr<>
将被删除。
是的,很安全。如果这不安全,那么 std::shared_ptr
将毫无用处。
"b" which is an instance of B will be released at the end of function foo.
是的,但是它的 std::shared_ptr<A>
是在那之前复制的。
让我们看看函数的最后一行到底做了什么:
return b.get_a();
get_a()
产生一个 std::shared_ptr<A>
,它被复制到一个临时对象。这个临时 std::shared_ptr<A>
对象然后被再次复制成为 main
.
中调用的结果
(由于 return-value 优化,实际副本甚至可能被省略,但这不会改变任何东西。如果有的话,它使安全性更加容易理解。)
只有then被b
销毁,但是里面的std::shared_ptr<A>
到时候已经被复制了
b
中的 std::shared_ptr<A>
实例也被销毁,但是 A
对象的内存没有 被释放。 这就是 std::shared_ptr
的全部要点 -- 它知道它被复制的频率,并且只有在最后一个副本被销毁时才释放动态分配的内存。
"a" in the main function is a shared_ptr of B::m_a.
没有。这是一个 std::shared_ptr<A>
,仅此而已。已经和原来的B::m_a
没有任何关系了。
Is it safe to use "a" after "b" is released?
是的,因为 a
和 b
之间没有持久的关系。
基本上,您是在质疑 C++ 的一项基本功能的安全性,即 return 从函数中获取值。就安全性而言,返回 std::shared_ptr
与 return 返回 std::string
或 int
没有什么不同。当您 return 通过函数的值时总是会发生这种情况:将要 returned 的值被复制,原始值被销毁,副本继续存在。
假设我有以下代码,这是我的问题的简化示例:
#include <string>
#include <iostream>
#include <memory>
class A{
public:
std::string name() { return "class A"; }
};
class B{
public:
B(){
m_a = std::make_shared<A>();
}
std::shared_ptr<A> get_a() { return m_a; }
private:
std::shared_ptr<A> m_a;
};
std::shared_ptr<A> foo()
{
B b;
return b.get_a();
}
int main()
{
auto a = foo();
auto name = a->name();
std::cout << name;
return 1;
}
我想知道这样做安全吗? "b" 是 B 的实例,将在函数 foo 结束时释放。 main函数中的"a"是B::m_a的shared_ptr。在 "b" 发布后使用 "a" 是否安全?
非常感谢!
那个foo
shared_ptr<A> foo()
{
B b;
return b.get_a();
}
不是 return 对 b 成员的引用,而是该成员的独立副本(副本的副本,如果未进行 RV 优化);和 shared_ptr
a
auto a = foo();
将 A 堆实例从破坏中保存到范围结束。
因此我认为这是安全的,B 们虽然是创作者,但毕竟只是他们创作和发布的许多共享资产的一个用户。
换句话说——最后一个关灯的,而不是开灯的那个。
很安全。
shared_ptr
在堆上创建一个跟踪变量。这使得对象 B
更加复杂,因为即使它是在堆栈上创建的,它也会从堆中分配一个 A
。可能会影响性能。
当跟踪数据的所有用户都停止访问它时,shared_ptr<>
将被删除。
是的,很安全。如果这不安全,那么 std::shared_ptr
将毫无用处。
"b" which is an instance of B will be released at the end of function foo.
是的,但是它的 std::shared_ptr<A>
是在那之前复制的。
让我们看看函数的最后一行到底做了什么:
return b.get_a();
get_a()
产生一个 std::shared_ptr<A>
,它被复制到一个临时对象。这个临时 std::shared_ptr<A>
对象然后被再次复制成为 main
.
(由于 return-value 优化,实际副本甚至可能被省略,但这不会改变任何东西。如果有的话,它使安全性更加容易理解。)
只有then被b
销毁,但是里面的std::shared_ptr<A>
到时候已经被复制了
b
中的 std::shared_ptr<A>
实例也被销毁,但是 A
对象的内存没有 被释放。 这就是 std::shared_ptr
的全部要点 -- 它知道它被复制的频率,并且只有在最后一个副本被销毁时才释放动态分配的内存。
"a" in the main function is a shared_ptr of B::m_a.
没有。这是一个 std::shared_ptr<A>
,仅此而已。已经和原来的B::m_a
没有任何关系了。
Is it safe to use "a" after "b" is released?
是的,因为 a
和 b
之间没有持久的关系。
基本上,您是在质疑 C++ 的一项基本功能的安全性,即 return 从函数中获取值。就安全性而言,返回 std::shared_ptr
与 return 返回 std::string
或 int
没有什么不同。当您 return 通过函数的值时总是会发生这种情况:将要 returned 的值被复制,原始值被销毁,副本继续存在。