如何在两个 STL 容器之间移动 unique_ptr 对象
how to move unique_ptr object between two STL containers
#include <utility>
#include<unordered_map>
#include<queue>
using namespace std;
struct Task {
char t;
int cnt;
Task(char ch, int cnt):t(ch), cnt(cnt){};
};
struct CompTask {
bool operator() (const unique_ptr<Task>& a, const unique_ptr<Task>& b) {
return a->cnt < b->cnt;
}
};
class Schedule {
public:
int schedule() {
unordered_map<unique_ptr<Task>, int> sleep_q;
priority_queue<unique_ptr<Task>, vector<unique_ptr<Task>>, CompTask> ready_q; // max heap
ready_q.push(std::make_unique<Task>('A', 1));
auto& ptr = ready_q.top();
//sleep_q.insert({ptr, 1}); // compile error
sleep_q.insert({std::move(ptr), 1}); // compile error
// some other code...
return 1;
}
};
int main() {
return 0;
}
// error:
cpp:38:17: error: no matching member function for call to 'insert'
sleep_q.insert({std::move(ptr), 1}); // compile error
~~~~~~~~^~~~~~
编程上下文:
我有一个任务 class 并且程序尝试模拟任务调度(这涉及在就绪队列和睡眠队列之间来回移动任务)。
我有两个标准容器分别用于就绪队列和睡眠队列,priority_queue 的值类型为 unique_ptr<Task>
,另一个是
unorder_map(休眠队列)其key也是unique_ptr<Task>
。我在将 unique_ptr 对象从 priorty_queue 移动到 unordered_map 时遇到了问题(如代码所示)。
我的问题是:
(1) 如何将项目插入 unordered_map,我在这样做时遇到了编译错误。
(2) 在问题上下文中,首选哪种类型的“指针”? unique_ptr<Task>, shared_ptr<Task>, or just Task*
要在 std 容器之间移动 unique_ptr
需要销毁一个 unique_ptr
(存储在第一个 std 容器中)并将支持数据传递给新的 unique_ptr
。这可以用 std::move
来完成。但是,通常使用 shared_ptr
更容易。这通过允许 shared_ptr
指向同一个任务同时位于两个 std 容器中来避免问题。哪怕只是一瞬间。
但是,由于您可能有多个 shared_ptr
对象指向同一个任务,因此 shared_ptr
无法唯一标识该任务。为此,我建议为每个任务创建一个任务 ID。只要您保证它对于该任务是唯一的,一个简单的整数就可以解决这个问题。整数任务 Id 可以很好地与地图配合使用,因为 Id 可以用作键。
std::priority_queue<>
似乎缺少移动功能。您可以使用 const_cast
绕过它,但在极少数情况下它可能会导致未定义的行为(当存储的元素类型为 const
时)。
int schedule() {
unordered_map<unique_ptr<Task>, int> sleep_q;
priority_queue<unique_ptr<Task>, vector<unique_ptr<Task>>, CompTask> ready_q; // max heap
ready_q.push(std::make_unique<Task>('A', 1));
unique_ptr<Task> ptr =
std::move(const_cast<unique_ptr<Task>&>(ready_q.top()));
// ^ Here. priority_queue::top() returns `const&`.
ready_q.pop(); // remove moved element from priority_queue
sleep_q.insert(std::make_pair(std::move(ptr), 1));
// some other code...
return 1;
}
参考:This answer
#include <utility>
#include<unordered_map>
#include<queue>
using namespace std;
struct Task {
char t;
int cnt;
Task(char ch, int cnt):t(ch), cnt(cnt){};
};
struct CompTask {
bool operator() (const unique_ptr<Task>& a, const unique_ptr<Task>& b) {
return a->cnt < b->cnt;
}
};
class Schedule {
public:
int schedule() {
unordered_map<unique_ptr<Task>, int> sleep_q;
priority_queue<unique_ptr<Task>, vector<unique_ptr<Task>>, CompTask> ready_q; // max heap
ready_q.push(std::make_unique<Task>('A', 1));
auto& ptr = ready_q.top();
//sleep_q.insert({ptr, 1}); // compile error
sleep_q.insert({std::move(ptr), 1}); // compile error
// some other code...
return 1;
}
};
int main() {
return 0;
}
// error:
cpp:38:17: error: no matching member function for call to 'insert'
sleep_q.insert({std::move(ptr), 1}); // compile error
~~~~~~~~^~~~~~
编程上下文:
我有一个任务 class 并且程序尝试模拟任务调度(这涉及在就绪队列和睡眠队列之间来回移动任务)。
我有两个标准容器分别用于就绪队列和睡眠队列,priority_queue 的值类型为 unique_ptr<Task>
,另一个是
unorder_map(休眠队列)其key也是unique_ptr<Task>
。我在将 unique_ptr 对象从 priorty_queue 移动到 unordered_map 时遇到了问题(如代码所示)。
我的问题是:
(1) 如何将项目插入 unordered_map,我在这样做时遇到了编译错误。
(2) 在问题上下文中,首选哪种类型的“指针”? unique_ptr<Task>, shared_ptr<Task>, or just Task*
要在 std 容器之间移动 unique_ptr
需要销毁一个 unique_ptr
(存储在第一个 std 容器中)并将支持数据传递给新的 unique_ptr
。这可以用 std::move
来完成。但是,通常使用 shared_ptr
更容易。这通过允许 shared_ptr
指向同一个任务同时位于两个 std 容器中来避免问题。哪怕只是一瞬间。
但是,由于您可能有多个 shared_ptr
对象指向同一个任务,因此 shared_ptr
无法唯一标识该任务。为此,我建议为每个任务创建一个任务 ID。只要您保证它对于该任务是唯一的,一个简单的整数就可以解决这个问题。整数任务 Id 可以很好地与地图配合使用,因为 Id 可以用作键。
std::priority_queue<>
似乎缺少移动功能。您可以使用 const_cast
绕过它,但在极少数情况下它可能会导致未定义的行为(当存储的元素类型为 const
时)。
int schedule() {
unordered_map<unique_ptr<Task>, int> sleep_q;
priority_queue<unique_ptr<Task>, vector<unique_ptr<Task>>, CompTask> ready_q; // max heap
ready_q.push(std::make_unique<Task>('A', 1));
unique_ptr<Task> ptr =
std::move(const_cast<unique_ptr<Task>&>(ready_q.top()));
// ^ Here. priority_queue::top() returns `const&`.
ready_q.pop(); // remove moved element from priority_queue
sleep_q.insert(std::make_pair(std::move(ptr), 1));
// some other code...
return 1;
}
参考:This answer