[英]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)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\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)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\tuple|353|required from 'constexpr std::_Tuple_impl<_Idx, _Head>::_Tuple_impl() [with unsigned int _Idx = 1u; _Head = <lambda(int*)>]'|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\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)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\tuple|602|required from 'constexpr std::tuple<_T1, _T2>::tuple() [with _T1 = int*; _T2 = <lambda(int*)>]'|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\unique_ptr.h|158|required from 'constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = <lambda(int*)>]'|
F:\3d\C++CodeProject\Hello\main.cpp|10|required from here|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\tuple|59|error: use of deleted function '<lambda(int*)>::<lambda>()'|
F:\3d\C++CodeProject\Hello\main.cpp|6|note: a lambda closure type has a deleted default constructor|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\unique_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:\3d\C++CodeProject\Hello\main.cpp|11|required from here|
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\unique_ptr.h|252|error: use of deleted function '<lambda(int*)>&<lambda(int*)>::operator=(const<lambda(int*)>&)'|
F:\3d\C++CodeProject\Hello\main.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的类型不是默认的可构造的 。 因此,指针类型的每个声明都需要传递一个删除器的实例。
您可以通过使用默认可构造的显式functor结构替换deleter 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所说,赋值行的问题也是(pre-c ++ 20)lambdas也不是CopyAssignable 。 我上面发布的仿函数方法修复了这两个问题。
两个问题。
std::unique_ptr
使用它作为删除器而不是DefaultConstructible。 闭包类型不是DefaultConstructible。 Closure类型有
a deleted (until C++14)
no (since C++14)
默认构造函数。 (直到C ++ 20)如果未指定捕获,则闭包类型具有默认的默认构造函数。 否则,它没有默认构造函数(这包括存在capture-default的情况,即使它实际上没有捕获任何东西)。 (自C ++ 20起)
std::unique_ptr
使用它作为删除器而不是CopyAssignable。 复制赋值运算符被定义为已删除(并且未声明移动赋值运算符)。 闭包类型不是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
或编写一个functor结构(参见其他答案)。
你得到的错误是因为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);
}
这样,您不必在没有对象管理时分配删除器,而且可以定义和使用始终随创建对象一起移动的其他删除器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.