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
。返回的对拥有内存,因此您不必担心删除它。Astd::pairstd::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() );