如何从库返回的原始指针创建unique_ptr并通过引用传递?是否有更优方案?
关于用unique_ptr接管库返回原始指针的问题解答
现有代码的有效性
你当前的实现是有效的:通过std::unique_ptr::reset()方法,成功将库返回的原始指针(假设由new分配)的所有权转移给了unique_ptr,代码能正常输出42也验证了这一点。结合MariaDB C++ Connector的示例代码(直接用driver->connect()的返回值初始化unique_ptr),可以确认该库确实用new创建Connection对象,因此默认的unique_ptr删除器(调用delete)是安全的。
更优的实现方案
虽然现有代码可行,但有两种更贴合C++最佳实践的写法:
方案1:直接返回unique_ptr(推荐,若可调整接口)
如果允许打破“返回bool表示成功状态”的惯例,直接返回unique_ptr是最清晰的写法——它明确传递了对象所有权转移的语义,无需额外的输出参数:
#include <memory> #include <iostream> class A { public: int b; A() : b(42) {} }; std::unique_ptr<A> create() { // 直接将库返回的原始指针包装为unique_ptr返回 return std::unique_ptr<A>(new A); // 实际场景替换为:return std::unique_ptr<A>(库函数调用); } int main() { auto foo = create(); std::cout << "foo.b is " << foo->b << '\n'; }
方案2:保持返回bool的同时优化实现
如果必须遵循现有代码的“返回bool”约定,可以保留引用传递,但补充错误处理逻辑(因为库函数可能在失败时返回nullptr或抛出异常):
#include <memory> #include <iostream> class A { public: int b; A() : b(42) {} }; bool create(std::unique_ptr<A>& p) { try { A* raw_ptr = new A; // 替换为实际的库函数调用,比如driver->connect(...) if (!raw_ptr) { return false; } p.reset(raw_ptr); return true; } catch (const std::exception& e) { // 处理库可能抛出的异常,比如MariaDB的sql::SQLException p.reset(); return false; } } int main() { std::unique_ptr<A> foo; if (create(foo)) { std::cout << "foo.b is " << foo->b << '\n'; } else { std::cout << "对象创建失败\n"; } }
这种写法既保持了和现有代码的一致性,又增加了鲁棒性,能处理库函数可能出现的错误情况。
内容的提问来源于stack exchange,提问作者QF0
相关产品推荐
相关产品推荐

