C++ C++;如何添加唯一的_ptr';s是一个向量

C++ C++;如何添加唯一的_ptr';s是一个向量,c++,stl,copy-constructor,unique-ptr,C++,Stl,Copy Constructor,Unique Ptr,简化代码: #include <queue> #include <memory> #include <vector> class Foo { public: Foo() {}; virtual ~Foo() {} }; int main() { std::queue<std::unique_ptr<Foo>> queue; auto element = std::make_unique<Foo&

简化代码:

#include <queue>
#include <memory>
#include <vector>

class Foo {
public:
    Foo() {};
    virtual ~Foo() {}
};

int main()
{
    std::queue<std::unique_ptr<Foo>> queue;
    auto element = std::make_unique<Foo>();
    queue.push(std::move(element));
    std::vector<std::queue<std::unique_ptr<Foo>>> vector;
    // Error 1
    vector.push_back(queue); 
    // Error 2
    vector.push_back(std::move(queue));
    // Error 3
    vector.push_back({});
    return 0;
}
#包括
#包括
#包括
福班{
公众:
Foo(){};
虚拟~Foo(){}
};
int main()
{
std::队列;
auto element=std::make_unique();
push(std::move(element));
std::向量;
//错误1
向量。推回(队列);
//错误2
vector.push_back(std::move(queue));
//错误3
向量。推回({});
返回0;
}
错误:

'std::unique_ptr>::unique_ptr(常量) std::unique_ptr&)':正在尝试 引用已删除的函数


很明显,复制unique_ptr的任务已经被删除,但我不想复制它。是吗?

这有点棘手。所有可以增加向量大小的
std::vector
函数都必须以异常安全的方式进行操作,前提是以下两种情况之一为真:

  • T
    有一个move构造函数,保证它不会抛出任何异常;或者

  • T
    有一个复制构造函数

因此,在大多数实现中,如果
T
声明了一个move构造函数
nothrow
或等效构造函数,
vector
将使用
T
的move构造函数进行这些操作。如果没有,并且
T
具有复制构造函数,
vector
将使用复制构造函数,即使
T
具有移动构造函数

这里的问题是,
std::queue
总是声明它有一个复制构造函数,即使该复制构造函数实际上无法实例化,并且总是声明它有一个可能抛出的移动构造函数,即使容器成员的移动构造函数保证它不会抛出

标准在[queue.defn]中指定了以下内容:

namespace std {
  template<class T, class Container = deque<T>>
  class queue {
    // ...
  public:
    explicit queue(const Container&);
    explicit queue(Container&& = Container());
    // ...
  };
}
备注:
noexcept
中的表达式相当于
是可构造的

  • 如果
    容器
    类型不可复制,则更改要删除的复制构造函数,通常使用以下语言完成:

    explicit queue(Container&& rhs = Container()) nothrow(see below);
    
    explicit queue(const Container&);
    
    备注:除非
    是可复制的
    真的
    ,否则此构造函数应定义为已删除


  • 是,
    push_back
    复制一份。要在适当的位置创建对象,请使用
    emplace_back
    。如果
    std::queue
    替换为
    std::vector
    ,则此操作有效;不适用于默认的队列基础层
    std::deque
    。但是,移动一个不在向量中的
    deque
    ,效果确实不错。Weird@M.M是的,您可以移动不在
    向量中的
    deque
    。但是,操作将不会是异常的
    vector
    就是不喜欢潜在的投掷动作(详见aschepler的答案)。我发现使用
    deque
    directly@M.M不知道你的意思。你能链接到一个例子吗?@M.M好的,是的。
    queue
    的移动构造函数也未声明为
    noexcept
    。这更令人惊讶,因为无论元素类型是什么,都应该可以移动一个
    deque
    ,这与
    vector
    不同,没有明显的原因。我发现谈论它。。。这就涉及到了分配器特性,这解释了为什么我无法用一个测试非nothrow\u move\u可构造类(而不是
    deque
    )重现问题。代码使用容器
    queue
    构建OK,所以可能
    deque
    是根本问题,而
    queue
    本身是OK的