Dav*_*óth 2 c++ reference smart-pointers
可以使用函数的指针返回,这在很多方面都很有用,但是否建议从该返回值中获取引用?
#include <iostream>
#include <memory>
using namespace std;
unique_ptr<int> give_a_number(){
return std::make_unique<int>(6);
}
int main(){
int& ret = *give_a_number();
return ret;
}
Run Code Online (Sandbox Code Playgroud)
根据消毒剂,没有发生泄漏:
user@comp: Scrapbook$ g++ main.cpp -fsanitize=address -g
user@comp: Scrapbook$
Run Code Online (Sandbox Code Playgroud)
所以参考以某种方式被清理,但我不明白为什么。清理是如何发生的,甚至 unque_ptr 如何能够跟踪数据。这应该被视为安全行为吗?这是社区中公认的用法吗?
wal*_*nut 10
这里没有泄漏。一般由拥有的对象std::unique_ptr是永远不会泄露,只要.release()不叫上所属std::unique_ptr。
但是,您的程序确实有未定义的行为,因为生命周期不正确。如果您存储指向拥有对象的引用或指针,您将承担一些责任以确保正确的对象生命周期。
give_a_number()返回,按值,std::unique_ptr拥有该int对象。这std::unique_ptr因此被物化为语句中的临时对象
int& ret = *give_a_number();
Run Code Online (Sandbox Code Playgroud)
您不会将此临时移动到任何持久std::unique_ptr实例中。所以当临时对象在语句结束时被销毁时,int它拥有的对象也被销毁。现在你的参考是悬而未决的。
然后在 中使用悬空引用return ret;,导致未定义的行为。
您可以存储对所拥有对象的引用,但如果这样做,您必须确保std::unique_ptr拥有该引用的实例比该引用的生命int周期更长,以避免生命周期问题。例如以下是好的:
int main(){
return *give_a_number(); // `std::unique_ptr` temporary outlives return value initialization
}
Run Code Online (Sandbox Code Playgroud)
int main(){
auto ptr = give_a_number(); // `ptr` lives until `main` returns
int& ret = *ptr;
return ret;
}
Run Code Online (Sandbox Code Playgroud)
通常,将智能指针存储在上述自动变量中并*ptr在需要时通过取消引用来获取对象更安全。std::unique_ptr如果它没有被移出,那么它拥有的和 对象会一直存在到块的末尾。
但是,例如通过*ptr引用传递给函数是完全正确的。由于ptr超过了这样的函数调用,所以不会有任何问题。
如果您*give_a_number()直接将参数作为参数传递给函数,这也有效,因为std::unique_ptr临时函数也将比这样的调用存活得更久。但在这种情况下,std::unique_ptr它拥有的和 对象将只存在到语句结束(完整表达式),而不是块结束。