在条件或循环中分配智能指针

Posted

技术标签:

【中文标题】在条件或循环中分配智能指针【英文标题】:Assign smart pointer in condition or loop 【发布时间】:2017-10-18 22:32:20 【问题描述】:

我正在更新一些 c++11 之前的代码以使用 c++11 unique_ptrs。

我不确定如何处理的一件事是旧代码何时使用指针赋值作为条件。例如

Object* obj;
while ( obj = C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() )

   // do something with obj
   delete obj;

鉴于 std::unique_ptr::reset 没有返回值,因此无法将其直接转换为:

std::unique_ptr< Object > obj;
while ( obj.reset( C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() ) )

   // do something with obj

那么,升级此代码以使用 unique_ptrs 的最简洁方法是什么?我能想到的最好的是:

std::unique_ptr< Object > obj;
obj.reset(  C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() );
while ( obj )

   // do something with obj
   obj.reset(  C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() );

但这会给库函数添加混乱的双重调用,理想情况下我想避免这种情况。

【问题讨论】:

如果你使用的是 C++17,它允许:while ( obj.reset( LIBRARY_CALL() ); obj ) @aschepler:现在怎么办? C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT 你是哪个delete?这很可疑。 可能我把这个例子简化得太多了——实际上,unique_ptr 是用一个自定义删除器定义的,它调用了库的清理函数。 @KerrekSB open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html,2016 年 6 月接受。 【参考方案1】:

怎么样:

while ( auto obj = std::unique_ptr<Object>( C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() ) )

   // do something with obj

【讨论】:

while 检查unique_ptr 是否为空(通过其bool 转换运算符),因此无需检查循环体内的obj 是否为空 你可以通过写while (std::unique_ptr&lt;Object&gt; obj LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() )来丢失自动。请注意,它必须是 C++ 库调用,而不是 C 库,因为 C 分配器和 C++ new/delete 不兼容。 答案方法的缺点是这限制了指针的范围,因此您不能break; 退出while循环并继续使用指针。 @BenVoigt,我喜欢auto 和左侧的定义。我真的很喜欢 Herb Sutter 在 CppCon 中提出的概念,他说类型定义正在向右移动。 范围限制对我来说是一个加分项 - 原始实现将循环直到返回 nullptr,因此循环之外的任何使用无论如何都是无效的。【参考方案2】:

如果你想让obj在循环外保持活跃,你可以使用逗号操作符:

std::unique_ptr< Object > obj;
while ( obj.reset(  C_LIBRARY_CALL_WHICH_RETURNS_NEW_OBJECT() ), obj )

    // do something with obj

【讨论】:

我以前从未遇到过这种逗号的用法 - 但在这种情况下,这是一个非常优雅的解决方案!

以上是关于在条件或循环中分配智能指针的主要内容,如果未能解决你的问题,请参考以下文章

C++编程经验:智能指针 -- 裸指针管得了的我要管,裸指针管不了的我更要管!

C++编程经验:智能指针 -- 裸指针管得了的我要管,裸指针管不了的我更要管!

智能指针的原理和实现

智能指针的原理和实现

动态内存1(动态内存与智能指针)

智能指针的原理及其应用