gpt4 book ai didi

c++ - 尝试将lambda函数放在队列上时发生一般分配器错误(可能与unique_ptr相关)

转载 作者:行者123 更新时间:2023-12-02 10:29:40 24 4
gpt4 key购买 nike

尝试将lambda函数放入队列时,出现了一般C++分配器错误。我猜可能与我的类unique_ptr中的Buffer有关。
我知道,当我添加一个unique_ptr时,会使其无法复制,因为unique_ptr删除了其复制构造函数。但是我可以将其复制到lambda函数的内部(不知道如何)。该问题似乎仅在我尝试复制lamdba函数本身时出现。

#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <queue>
typedef std::function<void()> Task;
std::queue<Task> tasks;

template <class T>
class Buffer final
{
public:
static Buffer fromOwned(T buffer, size_t size)
{
return Buffer(std::make_unique<T>(buffer), size);
}

Buffer(std::unique_ptr<T> buffer, size_t size)
{
_buffer = std::move(buffer);
_size = size;
}
size_t size() {
return _size;
}
private:
std::unique_ptr<T> _buffer;
size_t _size = 0;
};

int main()
{
auto b = Buffer<uint8_t*>::fromOwned(new uint8_t[1], 1);
auto f = [b]() mutable {
b.size();
};
tasks.emplace(f);
}
错误:
<source>: In function 'int main()':

<source>:34:12: error: use of deleted function 'Buffer<unsigned char*>::Buffer(const Buffer<unsigned char*>&)'

34 | auto f = [b]() mutable {

| ^~~~~~~~~~~~~~~

35 | b.size();

| ~~~~~~~~~

36 | };

| ~

<source>:10:11: note: 'Buffer<unsigned char*>::Buffer(const Buffer<unsigned char*>&)' is implicitly deleted because the default definition would be ill-formed:

10 | class Buffer final

| ^~~~~~

<source>:10:11: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = unsigned char*; _Dp = std::default_delete<unsigned char*>]'

In file included from /opt/compiler-explorer/gcc-trunk-20200709/include/c++/11.0.0/memory:83,

from <source>:3:

/opt/compiler-explorer/gcc-trunk-20200709/include/c++/11.0.0/bits/unique_ptr.h:468:7: note: declared here

468 | unique_ptr(const unique_ptr&) = delete;

| ^~~~~~~~~~

Compiler returned: 1
我尝试读取 new_allocator.h文件,但是它没有告诉我有关该错误的任何信息,该错误非常笼统。为什么会这样呢?有人提供阅读这些 super 通用错误的提示吗?
我尝试将复制和复制分配添加到该类:
        Buffer(Buffer &buffer) : _size(buffer._size),
{
_buffer = std::move(buffer._buffer);
}


Buffer &operator=(Buffer & buffer)
{
_size = buffer._size;
_buffer = std::move(buffer._buffer);
}

希望它不会依赖 unique_ptr的副本构造函数,但它没有做任何更改。

最佳答案

假设您使用的是C++ 14或更早版本,则需要在捕获中使用移动:

[b = std::move(b)]() mutable {
b.size();
}
现在开始详细说明...首先,您得到的错误是编译器尝试构建lambda捕获时发生的,而不是在复制lambda时发生的。由于 Buffer的副本构造函数被删除(由于 unique_ptr成员),因此您无法复制 Buffer对象。
您可以通过实现复制构造函数来解决该问题,但是您的实现并不完善,因为“复制”会窃取对象的所有权。您实际上应该复制缓冲区:
Buffer( const Buffer& other )
: _size( other._size )
, _buffer( std::make_unique< T >( *other._buffer ) ) // <- rely on the copy constructor of `T`
{
}

Buffer& operator=( Buffer other )
{
_size = other._size;
_buffer = std::move( other._buffer );

return *this; // <- you forgot this.
}
但是,您可以保留默认的move语义:
Buffer( Buffer&& other ) = default;
有了这些定义,您就可以按值(value)捕获。

关于c++ - 尝试将lambda函数放在队列上时发生一般分配器错误(可能与unique_ptr相关),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62810603/

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