如何移动std :: unique_ptr<从一个STL容器到另一个? [英] how to move an std::unique_ptr<> from one STL container to another?
问题描述
我有一个模板容器 MyContainer< std :: unique_ptr< Foo>> 其中具有
std :: deque< T>
和 std :: vector< T>
成员。
I have a template container MyContainer<std::unique_ptr<Foo>>
which has a std::deque<T>
and a std::vector<T>
member.
内部方法 send_to_purgatory_if(谓词)
,我想查看 m_taskdq
中的所有项目并从 m_purgatory
,如果谓词的评估结果为真。
Inside method, send_to_purgatory_if( predicate )
, I would like to look at all items in m_taskdq
and move items from m_taskdq
to m_purgatory
, if the predicate evaluates to true.
我遇到了两个问题:
- 我的迭代器
如果我从循环内部从m_taskdq中删除项目,它会被丢掉
- 我担心
std的状态:: unique_ptr<>
如果我分两步进行操作(问题第1行和第2行-第2行,我认为std :: unique_ptr<>
它指向的code>
是未定义的?)
- my iterator
it
gets trashed if I remove items from m_taskdq from inside the loop - I am worried about the state of the
std::unique_ptr<>
if I do the move in two steps (problem lines 1 and 2 - by line 2, I think thestd::unique_ptr<>
pointed to byit
is undefined?)
我应该如何解决此代码?
template <typename T>
class MyContainer
{
typedef std::function<bool(T&)> PREDICATE;
void send_to_purgatory_if( PREDICATE p )
{
// bad code -------------------------------------
for( auto it=m_taskdq.begin(); it!=m_taskdq.end(); ++it )
{
if ( p( *it ) )
{
m_purgatory.emplace_back( move( *it )); // problem line 1
m_taskdq.erase( it ); // problem line 2
}
}
// end bad code ---------------------------------
}
std::deque< T > m_taskdq;
std::vector< T > m_purgatory;
};
推荐答案
这确实是一个C ++ 98问题,关于移动语义的红鲱鱼。首先要问的是如何在C ++ 98中执行此操作:
This is really a C++98 question, with a red-herring concerning move semantics. The first thing to ask is how to do this in C++98:
std :: deque :: erase(iterator)
返回一个 iterator
,该元素引用被删除元素之后的元素。因此,首先开始工作:
std::deque::erase(iterator)
returns an iterator
that refers to the element after the one erased. So get that working first:
void send_to_purgatory_if( PREDICATE p )
{
for( auto it=m_taskdq.begin(); it!=m_taskdq.end();)
{
if ( p( *it ) )
{
m_purgatory.emplace_back(*it);
it = m_taskdq.erase(it);
}
else
++it;
}
}
现在很容易使其与C一起使用++ 11移动语义:
And now it is easy to make it work with C++11 move semantics:
void send_to_purgatory_if( PREDICATE p )
{
for( auto it=m_taskdq.begin(); it!=m_taskdq.end();)
{
if ( p( *it ) )
{
m_purgatory.emplace_back(std::move(*it));
it = m_taskdq.erase(it);
}
else
++it;
}
}
unique_ptr $从
taskdq
中移出的c $ c>在 emplace_back $之后变成空的
unique_ptr
c $ c>,然后在下一行将其删除。没有伤害,没有犯规。
The unique_ptr
moved from in taskdq
becomes a null unique_ptr
after the emplace_back
, and then it gets erased in the next line. No harm, no foul.
当发生擦除
时,从返回擦除
在增加迭代器方面做得很好。当没有 擦除时,按顺序进行正常的迭代器增量。
When there is an erase
, the return from the erase
does a good job at incrementing the iterator. And when there is no erase
, a normal iterator increment is in order.
这篇关于如何移动std :: unique_ptr<从一个STL容器到另一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!