C++ C++;:如何将unique_ptr推送到deque?
在我的项目中,我需要一个容器来保存指向数据单元实例的智能指针。我编写的类(简单示例):C++ C++;:如何将unique_ptr推送到deque?,c++,move-semantics,unique-ptr,C++,Move Semantics,Unique Ptr,在我的项目中,我需要一个容器来保存指向数据单元实例的智能指针。我编写的类(简单示例): 模板 类队列 { 公众: 无效推送(常数T和参数) { m_deque.向前推(参数); } 私人: std::deque m_deque; }; 然后我想推一个: int main() { Queue< std::unique_ptr<DataBox> > queue; std::unique_ptr<DataBox> d1(new DataBox(
模板
类队列
{
公众:
无效推送(常数T和参数)
{
m_deque.向前推(参数);
}
私人:
std::deque m_deque;
};
然后我想推一个:
int main()
{
Queue< std::unique_ptr<DataBox> > queue;
std::unique_ptr<DataBox> d1(new DataBox(11));
queue.push(d1);
return 0;
}
intmain()
{
队列队列;
std::unique_ptr d1(新数据盒(11));
排队推送(d1);
返回0;
}
VS2017编译器说我不能这样做:
错误C2280 std::unique\u ptr::unique\u ptr(const std::unique\u ptr&):尝试引用已删除的函数
据我所知,错误的原因是试图复制unique_ptr。但如果我将签名更改为:
void push(T&¶m){…}
以及函数调用
queue.push(std::move(d1))代码>
我又犯了这个错误。所以问题是-我应该如何实现将unique\u ptr
移动到队列的push()
?您应该修改类以处理仅移动类型:
template <typename T>
class Queue
{
public:
void push(const T & param)
{
m_deque.push_front(param);
}
void push(T&& param)
{
m_deque.push_front(std::move(param));
}
private:
std::deque<T> m_deque;
};
模板
类队列
{
公众:
无效推送(常数T和参数)
{
m_deque.向前推(参数);
}
无效推送(T&¶m)
{
m_deque.向前推(标准::移动(参数));
}
私人:
std::deque m_deque;
};
使用方法:
int main()
{
Queue< std::unique_ptr<DataBox> > queue;
std::unique_ptr<DataBox> d1(new DataBox(11));
queue.push(std::move(d1));
}
intmain()
{
队列队列;
std::unique_ptr d1(新数据盒(11));
push(std::move(d1));
}
您应该修改类以处理仅移动类型:
template <typename T>
class Queue
{
public:
void push(const T & param)
{
m_deque.push_front(param);
}
void push(T&& param)
{
m_deque.push_front(std::move(param));
}
private:
std::deque<T> m_deque;
};
模板
类队列
{
公众:
无效推送(常数T和参数)
{
m_deque.向前推(参数);
}
无效推送(T&¶m)
{
m_deque.向前推(标准::移动(参数));
}
私人:
std::deque m_deque;
};
使用方法:
int main()
{
Queue< std::unique_ptr<DataBox> > queue;
std::unique_ptr<DataBox> d1(new DataBox(11));
queue.push(std::move(d1));
}
intmain()
{
队列队列;
std::unique_ptr d1(新数据盒(11));
push(std::move(d1));
}
如果您想使其通用化,以便推送
可以采用l或r值,您可以尝试以下方法:
#include <iostream>
#include <memory>
#include <deque>
#include <utility>
class DataBox
{
public:
DataBox(int i) {}
};
template <typename T>
class Queue
{
public:
template <typename U>
void push(U &¶m)
{
m_deque.push_front(std::forward<T>(param));
}
private:
std::deque<T> m_deque;
};
int main()
{
Queue<std::unique_ptr<DataBox>> queue;
std::unique_ptr<DataBox> d1 = std::make_unique<DataBox>(11);
std::unique_ptr<DataBox> d2 = std::make_unique<DataBox>(22);
queue.push(d1);
queue.push(std::move(d2));
return 0;
}
#包括
#包括
#包括
#包括
类数据盒
{
公众:
数据盒(int i){}
};
样板
类队列
{
公众:
样板
无效推送(U&参数)
{
向前推(标准::向前(参数));
}
私人:
std::deque m_deque;
};
int main()
{
排队;
std::unique_ptr d1=std::make_unique(11);
std::unique_ptr d2=std::make_unique(22);
排队推送(d1);
push(std::move(d2));
返回0;
}
如果您想使其通用化,以便push
可以采用l或r值,您可以尝试以下方法:
#include <iostream>
#include <memory>
#include <deque>
#include <utility>
class DataBox
{
public:
DataBox(int i) {}
};
template <typename T>
class Queue
{
public:
template <typename U>
void push(U &¶m)
{
m_deque.push_front(std::forward<T>(param));
}
private:
std::deque<T> m_deque;
};
int main()
{
Queue<std::unique_ptr<DataBox>> queue;
std::unique_ptr<DataBox> d1 = std::make_unique<DataBox>(11);
std::unique_ptr<DataBox> d2 = std::make_unique<DataBox>(22);
queue.push(d1);
queue.push(std::move(d2));
return 0;
}
#包括
#包括
#包括
#包括
类数据盒
{
公众:
数据盒(int i){}
};
样板
类队列
{
公众:
样板
无效推送(U&参数)
{
向前推(标准::向前(参数));
}
私人:
std::deque m_deque;
};
int main()
{
排队;
std::unique_ptr d1=std::make_unique(11);
std::unique_ptr d2=std::make_unique(22);
排队推送(d1);
push(std::move(d2));
返回0;
}
您有以下选项
选项1:简洁且通常快速
template <typename T>
class Queue {
public:
void push(T param) {
m_deque.push_front(std::move(param));
}
private:
std::deque<T> m_deque;
};
template <typename T>
class Queue {
public:
void push(const T& param) {
m_deque.push_front(param);
}
void push(T&& param) {
m_deque.push_front(std::move(param));
}
private:
std::deque<T> m_deque;
};
这是最理想的解决方案,但可能有点过头了。如果T
可以有效移动(并且您应该努力使所有类型都可以有效移动),那么它的复制量与选项1完全相同:
Queue<std::vector<int>> q;
std::vector<int> v;
q.push(v); // one copy, both with option 1 and option 2
q.push(std::move(v)); // no copies, both with option 1 and option 2
队列q;
std::向量v;
q、 推(v);//一份副本,包括选项1和选项2
q、 推(标准::移动(v));//无副本,包括选项1和选项2
然而:
Queue<NotEfficientlyMovableType> q;
NotEfficientlyMovableType x;
q.push(x); // one copy with option 2, two copies with option 1
q.push(std::move(x)); // same (so it doesn't really make sense)
队列q;
注:正式可移动类型x;
q、 推(x);//一份带有选项2,两份带有选项1
q、 推送(标准::移动(x));//同样的(所以它没有真正的意义)
选项3:简洁、始终快速,但有注意事项
template <typename T>
class Queue {
public:
template <typename U>
void push(U&& param)
{
m_deque.push_front(std::forward<T>(param));
}
private:
std::deque<T> m_deque;
};
模板
类队列{
公众:
样板
无效推送(U&参数)
{
向前推(标准::向前(参数));
}
私人:
std::deque m_deque;
};
使用选项3,您只需编写一个函数,并且它总是执行最少的副本数(如选项2)。但是,它需要模板参数推断,这可能会破坏有效代码。例如,这适用于选项1和2,但不适用于选项3:
Queue<std::pair<int, int>> q;
q.push({1, 2});
队列q;
q、 推送({1,2});
您有以下选项
选项1:简洁且通常快速
template <typename T>
class Queue {
public:
void push(T param) {
m_deque.push_front(std::move(param));
}
private:
std::deque<T> m_deque;
};
template <typename T>
class Queue {
public:
void push(const T& param) {
m_deque.push_front(param);
}
void push(T&& param) {
m_deque.push_front(std::move(param));
}
private:
std::deque<T> m_deque;
};
这是最理想的解决方案,但可能有点过头了。如果T
可以有效移动(并且您应该努力使所有类型都可以有效移动),那么它的复制量与选项1完全相同:
Queue<std::vector<int>> q;
std::vector<int> v;
q.push(v); // one copy, both with option 1 and option 2
q.push(std::move(v)); // no copies, both with option 1 and option 2
队列q;
std::向量v;
q、 推(v);//一份副本,包括选项1和选项2
q、 推(标准::移动(v));//无副本,包括选项1和选项2
然而:
Queue<NotEfficientlyMovableType> q;
NotEfficientlyMovableType x;
q.push(x); // one copy with option 2, two copies with option 1
q.push(std::move(x)); // same (so it doesn't really make sense)
队列q;
注:正式可移动类型x;
q、 推(x);//一份带有选项2,两份带有选项1
q、 推送(标准::移动(x));//同样的(所以它没有真正的意义)
选项3:简洁、始终快速,但有注意事项
template <typename T>
class Queue {
public:
template <typename U>
void push(U&& param)
{
m_deque.push_front(std::forward<T>(param));
}
private:
std::deque<T> m_deque;
};
模板
类队列{
公众:
样板
无效推送(U&参数)
{
向前推(标准::向前(参数));
}
私人:
std::deque m_deque;
};
使用选项3,您只需编写一个函数,并且它总是执行最少的副本数(如选项2)。但是,它需要模板参数推断,这可能会破坏有效代码。例如,这适用于选项1和2,但不适用于选项3:
Queue<std::pair<int, int>> q;
q.push({1, 2});
队列q;
q、 推送({1,2});
您可能只是忘记了std::move
用于m_deque.push_front(std::move(param))代码>无关:如果C++14或更高版本可用,并且需要强异常安全性。连我都链接到