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 &&param)
    {
        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 &&param)
    {
        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或更高版本可用,并且需要强异常安全性。连我都链接到