gpt4 book ai didi

C++如何将unique_ptr的队列添加到 vector

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:37:39 29 4
gpt4 key购买 nike

简化代码:

#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;
}

错误:

'std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function

显然,复制 unique_ptr 的 c~tor 已被删除,但我并没有尝试复制它。我是吗?

最佳答案

这有点棘手。全部std::vector<T>如果以下两个条件之一为真,则可以增加 vector 大小的函数必须以异常安全的方式执行:

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

  • T有一个复制构造函数。

所以在大多数实现中,如果 T有一个声明为 nothrow 的移动构造函数或等效的,vector将使用 T 的移动构造函数对于那些操作。如果没有,和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());
// ...
};
}

可以通过多种方式改进此类模板定义,使其更加“SFINAE 友好”并避免出现您遇到的问题。 (也许有人可以检查其他有类似问题的类,然后向图书馆工作组提交提案。)

  1. 更改移动构造函数以保证在 Container 时不抛出type 做出相同的 promise ,通常使用如下语言完成:

    explicit queue(Container&& rhs = Container()) nothrow(see below);

    备注:里面的表达式noexcept相当于is_­nothrow_­move_­constructible_­v<Container> .

  2. 如果Container 改变要删除的复制构造函数类型不可复制,通常使用如下语言完成:

    explicit queue(const Container&);

    备注:除非is_­copy_­constructible_­v<Container>,否则该构造函数应定义为已删除是true .

关于C++如何将unique_ptr的队列添加到 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50690713/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com