我会考虑使用带有自定义析构函数的 shared_ptr 包装 ogg_stream_state。
class OggStreamState {
public:
shared_ptr<ogg_stream_state> state;
OggStreamState() :
state(new ogg_stream_state, &ogg_stream_clear)
{}
};
您的代码现在看起来像这样:
OggStreamState os;
ogg_stream_init(os.state.get(),ogg_page_serialno(&og));
这有点难看,但这种技术为开始转向面向对象的接口而不是基于 C 函数的接口提供了一个合乎逻辑的地方。
例如,您可以将ogg_stream_init 移动到OggStreamState,这样它就会变成
OggStreamState os;
os.init(ogg_page_seialno(&og));
再往前走一步,重复 ogg_page,你会得到
OggPage og = ...;
OggStreamState os;
os.stream_init(og.serialno());
您甚至可以将 init 一直拉到构造函数中
OggStreamState os(og.serialno());
或者在极端情况下......
OggStreamState os(og);
相对于纯哨兵 RAII(如 Lundin 的解决方案)的另一个优点是,您可以毫无问题地将 OggStreamState 传入和传出函数。编译器将确定您的最后一个引用何时被销毁并为您调用 clear 函数。即你可以安全地拥有一个
OggStreamState oss = function_that_returns_a_stream_state(...);
当然,这种技术确实会引入其他开销,但通常它们很少——而且它确实会稍微模糊 ogg 流的所有权,这很多或可能不是一件好事...