如何在自定义删除器的情况下复制unique_ptr
how to make copy of unique_ptr wih custom deleter
如果我使用自定义删除器复制unique_ptr,则会出现编译错误。请有人帮帮我.
#include <iostream>
#include<memory>
#include <algorithm>
using namespace std;
auto del = [](int *p) { cout <<"obj deleted "<<endl;delete p;};
int main()
{
unique_ptr<int, decltype(del)> p1(new int(10), del);
unique_ptr<int,decltype(del)> p2;
p2 = std::move(p1);
}
错误:
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++tuple||In instantiation of 'constexpr std::_Head_base<_Idx, _Head, true>::_Head_base() [with unsigned int _Idx = 1u; _Head = <lambda(int*)>]':|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++tuple|353|required from 'constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl() [with unsigned int _Idx = 1u; _Head = <lambda(int*)>]'|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++tuple|202|required from 'constexpr std::_Tuple_impl<_Idx, _Head, _Tail ...>::_Tuple_impl() [with unsigned int _Idx = 0u; _Head = int*; _Tail = {<lambda(int*)>}]'|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++tuple|602|required from 'constexpr std::tuple<_T1, _T2>::tuple() [with _T1 = int*; _T2 = <lambda(int*)>]'|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++bitsunique_ptr.h|158|required from 'constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = <lambda(int*)>]'|
F:3dC++CodeProjectHellomain.cpp|10|required from here|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++tuple|59|error: use of deleted function '<lambda(int*)>::<lambda>()'|
F:3dC++CodeProjectHellomain.cpp|6|note: a lambda closure type has a deleted default constructor|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++bitsunique_ptr.h||In instantiation of 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = <lambda(int*)>]':|
F:3dC++CodeProjectHellomain.cpp|11|required from here|
C:Program Files (x86)CodeBlocksMinGWlibgccmingw325.1.0includec++bitsunique_ptr.h|252|error: use of deleted function '<lambda(int*)>&<lambda(int*)>::operator=(const<lambda(int*)>&)'|
F:3dC++CodeProjectHellomain.cpp|6|note: a lambda closure type has a deleted copy assignment operator|
||=== Build failed: 2 error(s), 8 warning(s) (0 minute(s), 1 second(s)) ===|
您在声明p2
时遇到的问题是 lambda 的类型不是默认可构造的。因此,指针类型的每个声明都需要传递一个删除程序的实例。
您可以通过将删除程序 lambda 替换为默认可构造的显式函子结构来解决此问题。然后,指针类型的每个实例将能够创建自己的删除器对象实例。
struct MyDeleter
{
void operator()(int* p){cout << "deleted" << endl; delete p;}
};
int main()
{
//don't need to specify an instance of the deleter since it is default_constructible.
unique_ptr<int, MyDeleter> p1(new int(10));
unique_ptr<int, MyDeleter> p2;
p2 = std::move(p1);
}
编辑: 正如@super所说,赋值行的问题还在于(C++20之前(lambda也不是CopyAssignable的。我上面发布的函子方法解决了这两个问题。
两个问题。
- 在 C++20 之前,lambda 闭包类型不是 DefaultConstructible;这导致将其用作删除器的
std::unique_ptr
也不是 DefaultConstructible。
闭包类型不是默认构造的。闭包类型具有
a deleted (until C++14)
no (since C++14)
默认构造函数。(至C++20(如果未指定捕获,则闭包类型具有默认的默认构造函数。否则,它没有默认构造函数(这包括存在捕获默认的情况,即使它实际上没有捕获任何内容(。(自C++20起(
- 在 C++20 之前,lambda 闭包类型不是 CopyAssignable;这导致将其用作删除程序的
std::unique_ptr
也不是 CopyAssignable。
定义为已删除(并且未声明移动指派运算符(。闭包类型不可复制分配。(至C++20(
如果未指定捕获,则闭包类型具有缺省复制指派运算符和缺省移动指派运算符。否则,它有一个已删除的复制分配运算符(这包括存在捕获默认值的情况,即使它实际上没有捕获任何内容(。(自C++20起(
这意味着,您的代码将从 C++20 开始工作,因为 lambda 不指定捕获。在此之前,您可以改用std::function
;例如std::function<void(int*)> del = [](int *p) { cout <<"obj deleted "<<endl;delete p;};
您会收到一条错误消息,因为在这种情况下,unique_ptr上没有默认构造器,因此它们始终被启动
但你可以做到
auto del = [](int *p) { cout <<"obj deleted "<<endl;delete p;};
int main()
{
unique_ptr<int, decltype(del)> p1(new int(10), del);
unique_ptr<int,decltype(del)> p2(std::move(p1));
}
这里有两个错误(如错误消息所示(:您不能复制分配 lambda(在构造p1
时需要(,也不能默认构造 lambda(在p2
的默认初始化中需要(。
这将修复以下两个错误:
auto del = [](int *p) { cout <<"obj deleted "<<endl;delete p;};
int main()
{
unique_ptr<int, decltype(del)> p1(new int(10), std::move(del));
unique_ptr<int, decltype(del)> p2 = std::move(p1);
}
但请注意,您的 lambda 只有一个实例会以这种方式存在。要为多个唯一指针生成多个 lambda 实例,您可以从函数返回它,使用std::function
或编写函子结构(请参阅其他答案(。
您得到的错误是因为 lambda 不是默认构造的。当您声明p2
时,您不会传递参数以用作删除器,因此编译器抱怨无法默认构造它。
这个答案已经涵盖了使用自定义删除器的干净方法。但是,如果必须对同一类的对象使用不同的删除器,则必须在每个智能指针的构造中传递删除器,或者使用默认可构造的类型,以便nullptr
可以具有"null"删除器对象。
auto del = [](int *p) { cout << "obj deleted " << endl; delete p; };
int main() {
unique_ptr<int, std::function<void(int*)>> p1(new int(10), del);
unique_ptr<int, std::function<void(int*)>> p2;
p2 = std::move(p1);
}
这样,您不仅不必在没有管理对象时分配删除器,而且您可以定义和使用其他删除器,这些删除器始终与创建它们的对象一起移动。
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 在不复制临时对象的情况下延长其生存期
- 在这种情况下,我真的复制了字节还是复制了字符?
- QT QOpenGLWidget:如何在不使用数据块复制的情况下修改VBO中的单个顶点值?
- 如何在不复制的情况下将一个向量移动到另一个向量中
- 如何在没有复制构造函数的情况下为地图设置值?
- 在这种情况下,使用 string_view 是否会导致不必要的字符串复制?
- 我有两棵二叉树.我想在不更改输入树的情况下深度复制两个二叉树的结果
- 如何在不复制的情况下操作 QByteArray 对象?
- 在不复制数据的情况下,将double数组转换为只有double成员的structs数组
- 有没有一种方法可以在不复制数据的情况下从string_view创建字符串流
- 是否可以在不复制的情况下访问undered_map中的元素
- 如何在不复制数据的情况下将 cv::Mat 转换为 2d 标准::矢量
- 如何在不复制列表的情况下将列表传递给线程,同时销毁原始列表
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 是否可以在不显式迭代每个元素的情况下深度复制指针容器?
- 如何在不复制此代码的情况下将多个函数放入多个命名空间?
- 父类有 26 个构造函数重载.如何在不复制+粘贴 26 个重载的情况下将一个小任务附加到所有构造器?
- 如何在自定义删除器的情况下复制unique_ptr
- 如何在不复制的情况下比较字符串的一部分?