【问题标题】:How to use smart pointer from function that returns a raw pointer [duplicate]如何使用返回原始指针的函数中的智能指针[重复]
【发布时间】:2021-06-07 12:58:13
【问题描述】:

我有一个需要使用的 C++ 库,它使用 build() 函数通过原始指针返回带有 new 的对象。我想在使用智能指针时使用这个对象,但到目前为止,我只找到了使用 smart_ptr.reset(build()) 的解决方案,它有效但有点难看。有没有更好的方法或者我必须使用手动内存管理?

对于更多上下文,库中的函数调用return new,我相信您需要在该指针上调用 delete。

How to assign the address of an existing object to a smart pointer? 这是我之前称之为“丑陋”的答案,也是我问是否有更好的方法的原因。

【问题讨论】:

  • 可行但有点丑 -- 还是我必须使用手动内存管理? -- 所以你愿意付出使用智能指针,因为它看起来(根据你)“丑陋”?这是一个奇怪的权衡。
  • 把丑陋的线放到漂亮的函数里,用that
  • 如果你有一个返回原始拥有指针的遗留函数,添加一个包装器来获得干净的代码似乎很好。
  • 对不起,我措辞不好。我并不是说我发现它很丑,而是我读到的答案说它很丑,应该不惜一切代价避免它。由于线程已有 5 年历史,我想知道现在是否有更好的方法。我绝不是说我不想使用智能指针。感谢其他答案,我将使用包装函数来完成。
  • 您应该确定谁应该删除该对象。你还是图书馆?也许你应该使用自定义删除器,也许不。

标签: c++ smart-pointers


【解决方案1】:

这取决于。考虑这个例子:

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返回的指针不会遇到问题。

Complete example:

#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) 进行正确清理,在这种情况下,您可以将库清理函数包装在自定义删除器中。

【讨论】:

  • 或者最好返回std::unique_ptr
  • @StefanRiedel 误读了要问shared_ptr 的问题,但它没有...
  • 为什么不是数字?
  • @HattedRooster 有一个非常不有趣的故事,你可以在我的个人资料中阅读它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 2018-03-22
  • 1970-01-01
  • 2016-08-01
  • 2014-07-25
  • 2022-01-23
相关资源
最近更新 更多