关于If-with-initializer生存期扩展与std::out_ptr代码是否存在潜在问题的疑问
关于If-with-initializer生存期扩展与std::out_ptr代码是否存在潜在问题的疑问
我最近看到P1132里把一段使用std::out_ptr配合if初始化器的代码标记为潜在的陷阱,实在搞不懂为什么这会是个问题。
先看P1132里提到的这段被标记为footgun的代码:
std::unique_ptr<foo_handle, foo_deleter> my_unique(nullptr); if (get_some_pointer(std::out_ptr(my_unique)); my_unique) { std::cout << "yay" << std::endl; } else { std::cout << "oh no" << std::endl; }
P1132给出的理由是:例如,在同一个if语句中既完成初始化操作又测试智能指针的话,会以非常不合理的顺序进行生存期扩展。
但我始终想不通这里的问题所在:我们真正需要保证的是std::out_ptr的析构函数能在测试my_unique之前运行,从而完成对my_unique的重置。可if初始化器只会延长get_some_pointer()返回值的生存期(这里甚至都没把返回值赋值给任何变量),根本不会延长传入参数的生存期啊。
为了验证自己的想法,我写了一个小测试程序来模拟这个场景:
#include <iostream> struct s { int i = []() { static int i = 0; return i++; }(); s() { std::cout << i << ": ctor\n"; } ~s() { std::cout << i << ": dtor\n"; } operator bool() { std::cout << i << ": bool\n"; return false; } }; template <typename... Ts> s foo(Ts&&...) { return s{}; } int main(int, const char**) { s x{}; if (foo(s{}); x) { std::cout << " : true\n"; } else { std::cout << " : false\n"; } }
我运行这段代码后,得到的输出是:
0: ctor 1: ctor 2: ctor 2: dtor 1: dtor 0: bool : false 0: dtor
从输出结果能清楚看到:foo()的参数临时对象和返回值临时对象,都是在测试x(对应原问题中的my_unique)之前就已经完成析构了。这完全符合我的预期——临时对象的析构会在if初始化器执行完毕、进入条件判断逻辑之前完成。
那我是不是漏掉了什么关键细节?还是说P1132里的这个说法其实并不准确?
内容来源于stack exchange
相关产品推荐
相关产品推荐

