C++ 智能指针std::pair的元素

C++ 智能指针std::pair的元素,c++,c++11,smart-pointers,C++,C++11,Smart Pointers,我有一个函数,它返回一个std::pair。函数的文档中说,我有责任取消分配这两个元素。现在我只是在做: { std::pair<objectA*, objectB*> the_pair; ... if (condition) { delete the_pair.first; delete the_pair.second; return; } ... delete the_pair.first; delete the_

我有一个函数,它返回一个
std::pair
。函数的文档中说,我有责任取消分配这两个元素。现在我只是在做:

{
  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;
}
{
std::对_对;
...
如果(条件){
首先删除_对;
删除_对。秒;
返回;
}
...
首先删除_对;
删除_对。秒;
}

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

如果我理解正确,则调用者有责任删除指针。在这种情况下,您可以创建一个唯一的\u 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
{//somescope
std::pair the_pair=_函数();
std::unique_ptr pffirst(第一对);
std::unique_ptr pssecond(第二对);
}//指针被删除
或者,您可以编写自己的范围保护:

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_;
};
struct pointer\u pair\u guard
{
指针对保护(std::pair&p):p(p){}
~pointer\u pair\u guard()
{ 
首先删除p_;
删除第二页;
}
指针对保护(常量指针对保护&)=删除;
指针对保护和运算符=(常量指针对保护&)=删除;
私人:
std::pair&p;
};
然后

{//somescope
std::pair the_pair=_函数();
指针对保护gd(指针对);
}//指针被删除
我很想存根函数并使用存根

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));
}
std::pair< std::共享ptr, std::共享的ptr >尼斯·富奥(…) { std::pair temp=bad_foo(…); 返回std::pair< std::共享ptr, std::共享的ptr >(std::shared_ptr(温度第一)、std::shared_ptr(温度第二)); }
在代码中,不要调用
bad\u foo
,而是调用
nice\u foo
。返回的对拥有内存,因此您不必担心删除它。

A
std::pair
std::pair
@TheOne我认为您有点误读了这个问题。是的,看起来是这样,但问题也不是很清楚+1喜欢它,特别是因为如果库供应商更改了他们的内存策略,您只需要调整防护等级。什么是
(\u p)
?你是说
p(p)
?我得到:
过时的老式基类初始值设定项
@RuggeroTurra,这是一个打字错误。应该是
p(p)
。防护的另一个优点是,您可以为这两个值指定比
第一个
第二个
更重要的名称。(使用
std::pair
几乎是一种反模式,除非在极少数情况下
第一个
第二个
是合适的名称。)没有@juanchopanza的解决方案那么可爱,因为您必须复制函数参数列表:+1;你不是在重复你自己,而是在重复别人:-)@Bathsheba我认为这对于库函数的一次性使用来说是可以的。
take\u ownersip
将左值传递给
tuple\u cast
,因此可能也会有不必要的副本(源类型可能不仅包含指针,也可能已经包含一些
unique\u ptr
). 我想你的意思是
返回tuple_cast(std::move(t))。另外,我认为
take_ownership
应该只接受在调用站点对左值源对象强制调用
std::move
的右值,这样即使读者不知道
take_ownership
做了什么,调用后源对象也不再可用。@casey说得好。另一方面,
take_ownership
排序意味着它将从输入参数获取所有权。不过,
std::move
告诉调用站点,元组/对不再可信,这很好。还有两个问题:(1)
tuple
的值构造函数是显式的。(2)
不能从
元组转换@Casey我不喜欢将目标“tuple”类型传递给
tuple\u cast
——这不是完美的,但它避免了这一点。
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));
}
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);
}
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() );