问题描述
我有一个模板容器 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_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 the std::unique_ptr<> pointed to by it 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容器到另一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!