c++ - 如何从返回原始指针的函数中使用智能指针
问题描述
我有一个需要使用的 C++ 库,它使用 build() 函数通过原始指针返回带有 new 的对象。我想在使用智能指针的同时使用这个对象,但到目前为止,我只找到了使用 smart_ptr.reset(build()) 的解决方案,它有效但有点难看。有没有更好的方法来做到这一点,还是我必须使用手动内存管理?
对于更多上下文,库中的函数会调用return new
,我相信您需要在该指针上调用 delete。
如何将现有对象的地址分配给智能指针?这是我之前称之为“丑陋”的答案,也是我问是否有更好的方法的原因。
解决方案
这取决于。考虑这个例子:
struct example {
~example() { std::cout << "bye\n"; }
};
example* some_lib_function_A(){
return new example;
}
该库返回一个指向动态分配对象的原始指针。这不好,为了避免处理原始的拥有指针,您可以包装some_lib_function_A
到一个函数中,该函数返回一个管理对象的智能指针。
但是,库也可能会沿着这条线做一些事情(只是为了论证。它应该返回一个引用):
example* some_lib_function_B() {
static example ex;
return &ex;
}
在这种情况下,您不能delete
在不遇到问题的情况下返回指针。
#include <memory>
#include <iostream>
struct example {
~example() { std::cout << "bye\n"; }
};
example* some_lib_function_A(){
return new example;
}
example* some_lib_function_B() {
static example ex;
return &ex;
}
template <typename F>
std::unique_ptr<example> wrap(F f){
std::unique_ptr<example> res;
res.reset(f());
return res;
}
int main() {
wrap(some_lib_function_A);
wrap(some_lib_function_B); // free(): invalid pointer
}
中的第一行符合main
您的预期,但第二行会导致未定义的行为。这就是链接答案说按照以下方式编写函数不好的原因:
std::unique_ptr<example> wrap_bad(example& ex) {
std::unique_ptr<example> res;
res.reset(&ex);
return res;
}
因为您无法知道example
传递给函数的是否是动态分配的。该函数对它的作用撒谎,因为获取引用的函数在处理其参数的生命周期方面没有任何业务。它可以正确使用,但错误使用的可能性很大。
您必须阅读库文档并找出库希望您使用指针做什么。有时您必须调用一些库函数clean_up(ex)
来进行适当的清理,在这种情况下,您可以将库清理函数包装在自定义删除器中。
推荐阅读
- amazon-web-services - 用于 sysmin 日志的 AWS Cloudwatch 代理配置
- python - 如何减少 Python 中的许多 if 语句?
- typescript - 如何在 TypeScript 中编写 typeof val === "undefined" 辅助函数?
- shell - 如何在 telnet 会话中循环执行命令
- amazon-web-services - 在 Keda 中对 AWS SQS 缩放器进行身份验证
- php - Laravel 请求路由并检查用户是否通过 ajax 登录
- mysql - 减去基于使用 MySQL 的数据的值
- docker - 如何在 Dockerfile 中使用暴露
- node.js - 延迟执行异步函数数组,节点js
- flutter - 从 Firebase 加载数据缓慢导致“RangeError(索引)”