【发布时间】:2017-10-30 12:36:50
【问题描述】:
考虑一个定义用于创建、销毁和使用自定义结构的函数的 C 库
struct Foo;
void foo_action(Foo*);
Foo* foo_create();
void foo_free(Foo*);
目前,我在我的 C++ 项目中使用该库如下
Foo* myfoo = foo_create();
foo_action(myfoo);
foo_free(myfoo);
我了解为什么智能指针很重要,并希望迁移我的代码以使用它们。 这就是代码现在的样子。
#include <memory>
#include <functional>
typedef std::unique_ptr<Foo, std::function<void(Foo*)>> FooPtr;
// ...
FooPtr myfoo2(foo_create(), foo_free);
foo_action(myfoo2.get());
它似乎有效,但 myfoo2.get() 调用似乎很老套。 我是否按预期使用它?
库的另一部分创建并使用某种列表结构。 api看起来像
struct Bar;
Bar* bar_append(Bar*, int);
void bar_free_recursive(Bar*);
并用作
// using NULL as current Bar* creates the initial structure
Bar* bar = bar_append(NULL, 1);
// each invocation leads to another 'head' structure
bar = bar_append(bar, 42);
bar = bar_append(bar, 123);
由于每次bar_append 调用都会改变指针(指向的地址),我将如何在此处引入智能指针,以便在释放指针实例时对当前指针值调用bar_free_recursive?
【问题讨论】:
-
记住你可以重载函数。为什么不创建一个简单的内联重载
foo_action函数,该函数接受FooPtr参数,并使用原始非智能指针调用旧的foo_action函数?您仍然可以保留旧代码,同时使界面更美观。 -
@Someprogrammerdude 好点,谢谢。我只是不确定是否需要它,或者是否有更直接的转换方式。
-
使用
std::function作为你的deleter会比制作一个特定的deleter效率低。 -
@Someprogrammerdude 我不认为
foo_action应该特定于某种特定类型的智能指针,如果它没有获得所有权。我怀疑foo_action可能应该采用Foo&,然后调用代码只是*myfoo2,无论指针类型如何。 -
似乎没有人解释为什么使用自己的删除器比使用
std::function或函数指针更有效。这是因为使用std::function或者函数指针需要std::unique_ptr来存储删除器;它是在运行时设置的。所以sizeof(std::unique_ptr<T>)将不再是T*。此外,std::unique_ptr的神奇特性之一是编译器通常能够优化它。编译器将更难内联std::function或函数指针。
标签: c++ smart-pointers