直接测试下,代码如下:
cpp
// 模拟C库,malloc分配,free释放
struct MyObj {
int val;
};
// C风格函数:分配内存,二级指针输出结果。这里只是模拟,真实c库异常时直接返回错误码,没有c++的抛异常语法。
void create_obj(MyObj** out) {
*out = (MyObj*)malloc(sizeof(MyObj));
if (*out == nullptr) {
throw std::runtime_error("malloc fail...");
}
(*out)->val = 9527;
std::cout << "[C库 malloc] 分配MyObj,地址:" << *out << "\n";
}
// C风格释放函数,配套malloc,用free
void free_obj(MyObj* p) {
if (p) {
std::cout << "[C库 free] 释放MyObj,地址:" << p << "\n";
free(p);
}
}
// 老式写法(可能会有异常安全漏洞)
void old_style_demo()
{
std::cout << "老式写法\n";
MyObj* raw = nullptr;
create_obj(&raw);
std::cout << "obj val = " << raw->val << "\n";
// 其他代码。。。
// 万一这里有异常,不会调用到下面的释放内存。可以加try catch捕获异常,异常时也调用释放,但是业务复杂也可能忘记调用释放。
free_obj(raw);
raw = nullptr;
}
// C++23 std::out_ptr 新写法
// create_obj执行完毕,资源立刻被智能指针接管,不管后续正常返回还是抛异常,unique_ptr 析构自动释放,编译器保证执行。
void new_outptr_demo()
{
std::cout << "C++23 std::out_ptr 写法" << "\n";
// 自定义删除器:指定释放函数 free_obj
std::unique_ptr<MyObj, decltype(&free_obj)> up(nullptr, free_obj);
// out_ptr 自动生成 MyObj** 传给C API
create_obj(std::out_ptr(up));
std::cout << "obj val = " << up->val << "\n";
// 离开作用域,unique_ptr自动调用free_obj释放,无需手动写释放
}
void testOutPtr(void) { // 测试c++23 std::out_ptr
old_style_demo();
new_outptr_demo();
}
执行testOutPtr函数:

ok. std::out_ptr + unique_ptr是推荐用法。比手动调用释放内存更智能化,不用担心忘记调用。