繁体   English   中英

智能指针std :: pair的元素

[英]smart pointer the element of a std::pair

我有一个返回std::pair<objectA*, objectB*>的函数。 该函数的文档说我有责任释放这两个元素。 现在我只是在做:

{
  std::pair<objectA*, objectB*> the_pair;

  ...

  if (condition) {
     delete the_pair.first;
     delete the_pair.second;
     return;
  }

  ...

  delete the_pair.first;
  delete the_pair.second;
}

the_pair超出范围时,如何使用智能指针自动删除这两个元素?

如果我理解正确,调用者有责任删除指针。 在这种情况下,您可以创建一个unique_ptr来管理该对的每个元素:

{ // some scope

  std::pair<objectA*, objectB*> the_pair = the_function();
  std::unique_ptr<objectA> pfirst(the_pair.first);
  std::unique_ptr<objectB> psecond(the_pair.second);

} // pointers get deleted

或者,您可以编写自己的范围保护:

struct pointer_pair_guard
{
  pointer_pair_guard(std::pair<objectA*, objectB*>& p) : p_(p) {}
  ~pointer_pair_guard() 
  { 
    delete p_.first;
    delete p_.second;
  }
  pointer_pair_guard(const pointer_pair_guard&) = delete;
  pointer_pair_guard& operator=(const pointer_pair_guard&) = delete;
  private:
    std::pair<objectA*, objectB*>& p_;
};

然后

{ // some scope

  std::pair<objectA*, objectB*> the_pair = the_function();
  pointer_pair_guard gd(the_pair);

} // pointers get deleted

我很想把这个函数存根并使用存根。

std::pair<
    std::shared_ptr<objectA>,
    std::shared_ptr<objectB>
> nice_foo(...)
{
    std::pair<objectA*, objectB*> temp = bad_foo(...);    
    return std::pair<
        std::shared_ptr<objectA>,
        std::shared_ptr<objectB>
    >(std::shared_ptr<objectA>(temp.first), std::shared_ptr<objectB>(temp.second));
}

在你的代码中,不要调用bad_foo ,而是调用nice_foo 返回的对拥有内存,因此您无需担心删除它。

std::pair<std::unique_ptr<A>,std::unique_ptr<B>>是显而易见的解决方案。 但我们希望它在使用时保持清洁。 所以:

template<class...Ts, template<class...>class tup, class... Us, size_t...Is>
tup<Ts...> tuple_cast(std::index_sequence<Is...>,tup<Us...>&&u){
  return tup<Ts...>{static_cast<Ts>(std::get<Is>(std::move(u)))...};
}
template<class...Ts, template<class...>class tup, class... Us, size_t...Is>
tup<Ts...> tuple_cast(std::index_sequence<Is...>,tup<Us...>const&u){
  return tup<Ts...>(static_cast<Ts>(std::get<Is>(u))...);
}
template<class...Ts, template<class...>class tup, class... Us>
tup<Ts...> tuple_cast(tup<Us...>&&u){
  static_assert( sizeof...(Ts)==sizeof...(Us), "must map one type to one type" );
  return tuple_cast<Ts...>(std::index_sequence_for<Us...>{}, std::move(u));
}
template<class...Ts, template<class...>class Tup, class... Us>
Tup<Ts...> tuple_cast(Tup<Us...>const&u){
  static_assert( sizeof...(Ts)==sizeof...(Us), "must map one type to one type" );
  return tuple_cast<Ts...>(std::index_sequence_for<Us...>{}, u);
}

now auto x = tuple_cast<std::unique_ptr<A>,std::unique_ptr<B>>( func() )是一种auto x = tuple_cast<std::unique_ptr<A>,std::unique_ptr<B>>( func() )针对转换为一对唯一指针的方法。

我们可以做得更好。

template<class A>
struct as_unique{using type=A;};
template<class A>
struct as_unique<A*>{using type=std::unique_ptr<A>;};
template<class A>
using as_unique_t=typename as_unique<A>::type;

template<class...Ts, template<class...>class tup>
tup<as_unique_t<Ts>...> take_ownership(tup<Ts...>&& t){
  return tuple_cast<as_unique_t<Ts>...>(std::move(t));
}

如果错别字是固定的,我们得到:

auto p = take_ownership( func() );

在使用时看起来更干净。 2这将获取std::pairstd::tuple任何指针值T* ,将它们转换为std::unique_ptr<T> s,为输出生成相应的类型,然后使用static_cast转换每个字段以使转换显式。

实例

以上使用C ++ 14索引序列。 它们可以用十几行左右的C ++ 11编写,所以我并不觉得它很糟糕。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM