前言:
现在大家对“unique函数怎样不显示错误”大体比较重视,各位老铁们都需要了解一些“unique函数怎样不显示错误”的相关资讯。那么小编也在网上汇集了一些关于“unique函数怎样不显示错误””的相关内容,希望同学们能喜欢,各位老铁们快快来了解一下吧!为什么需要用智能指针来管理我们的资源呢?
例如,一个二进制文件写入程序
std::ofstream ofile("sample.bin", std::ios::binary); if(!ofile.is_open()) { std::cout << "open file error." << std::endl; return; } std::vector<int> v{1,2,3,4,5}; for(const auto& i : v) { ofile.write(reinterpret_cast<const char*>(&i), sizeof(i)); } ofile.close();
我们一般会认为,程序总是会执行到ofile.close()的;但事实上,总会有各种各样的错误或是异常,从而导致程序无法执行到ofile.close();进而导致资源泄漏的发生。更明智的做法,是依托于作用域,来管理资源。
上面这段程序,可以改写成,如下形式:
auto fclose = [](auto fptr) { fptr->close(); delete fptr;}; auto fptr = new std::ofstream{"sample1.bin", std::ios::binary}; std::unique_ptr<std::ofstream, decltype(fclose)> uptr{fptr, fclose}; if(!uptr->is_open()) { std::cout << "open file error." << std::endl; return; } std::vector<int> v{1,2,3,4,5}; for(const auto& i : v) { uptr->write(reinterpret_cast<const char*>(&i), sizeof(i)); }
当然也可以,写成一行代码的形式
std::unique_ptr<std::ofstream, std::function<void(std::ofstream *)>> uptr(new std::ofstream{"sample.bin", std::ios::binary}, [](std::ofstream *fptr) { fptr->close(); delete fptr; });
读文件
auto fclose = [](auto fptr) { fptr->close(); delete fptr; }; auto fptr = new std::ifstream{"sample1.bin", std::ios::binary}; std::unique_ptr<std::ifstream, decltype(fclose)> uptr{fptr, fclose}; if (!uptr->is_open()) { std::cout << "open file error." << std::endl; } std::vector<int> v; while (true) { int i; uptr->read(reinterpret_cast<char *>(&i), sizeof(i)); if (uptr->fail() || uptr->eof()) break; v.emplace_back(i); } for (const auto &i : v) { cout << i << endl; }std::unique_ptr
std::unique_ptr的构造函数,接受两个参数:
一个数据指针,(这个指针可以指向单一数据,也可以是一个数组指针)一个析构函数,在unique_ptr脱离作用域时调用
unique_ptr(pointer _Ptr, const _Dx& _Dt)
所以,std::unique_ptr的类成员变量是一个类似pair的类,第一个元素为析构函数,第二个元素为数据指针。
_Compressed_pair<_Dx, pointer> _Mypair
我们在构造一个std::unique_ptr实例时,需要显示地指明数据指针类型和析构函数类型,数据指针类型比较容易得到,但析构函数类型如何得到了?
有两种方法:
利用decltype得到析构函数类型利用std::function来显示地指明析构函数类型
std::unique_pt在不显示指明析构函数时,会加载默认的析构函数
struct default_delete { // default deleter for unique_ptr constexpr default_delete() noexcept = default; template <class _Ty2, enable_if_t<is_convertible_v<_Ty2*, _Ty*>, int> = 0> default_delete(const default_delete<_Ty2>&) noexcept {} void operator()(_Ty* _Ptr) const noexcept /* strengthened */ { // delete a pointer static_assert(0 < sizeof(_Ty), "can't delete an incomplete type"); delete _Ptr; }};~unique_ptr() noexcept { if (_Mypair._Myval2) { _Mypair._Get_first()(_Mypair._Myval2); } }
这个析构函数就做了一件事,调用delete _Ptr来释放内存,它的传入参数是_Ty* _Ptr,由此可得到用std::function表示的析构函数类型
std::function<void(T*)>
结合上面的例子,可以写成
std::unique_ptr<std::ofstream, std::function<void(std::ofstream *)>> uptr(new std::ofstream{"sample.bin", std::ios::binary}, [](std::ofstream *fptr) { fptr->close(); delete fptr; });
而利用decltype得到析构函数类型比较简单,一路auto过去就行。
auto fclose = [](auto fptr) { fptr->close(); delete fptr;}; auto fptr = new std::ofstream{"sample1.bin", std::ios::binary}; std::unique_ptr<std::ofstream, decltype(fclose)> uptr{fptr, fclose};
另外在std::unique_ptr中有两个成员函数,比较容易混淆,即
pointer release() noexcept { return _STD exchange(_Mypair._Myval2, nullptr); } void reset(pointer _Ptr = nullptr) noexcept { pointer _Old = _STD exchange(_Mypair._Myval2, _Ptr); if (_Old) { _Mypair._Get_first()(_Old); } }
从上面的源码中,可以看出,release()并不释放内存,仅仅只是将std::unique_ptr中的数据指针置空并抛出数据指针;而reset(pointer _Ptr = nullptr)会调用析构函数,释放内存。
std::make_unique
template <class _Ty, class... _Types, enable_if_t<!is_array_v<_Ty>, int> = 0>_NODISCARD unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr return unique_ptr<_Ty>(new _Ty(_STD forward<_Types>(_Args)...));}template <class _Ty, enable_if_t<is_array_v<_Ty> && extent_v<_Ty> == 0, int> = 0>_NODISCARD unique_ptr<_Ty> make_unique(const size_t _Size) { // make a unique_ptr using _Elem = remove_extent_t<_Ty>; return unique_ptr<_Ty>(new _Elem[_Size]());}
unique_ptr<_Ty>(new _Ty(_STD forward<_Types>(_Args)...))
从这一行代码中,可以看出,make_unique仅能new出一个数据指针,而无法指定析构函数。所以需要自定义析构函数的时候,不能调用make_unique函数,来产生std::unique_ptr
// auto uptr = std::make_unique<std::ofstream, std::function<void(std::ofstream *)>>// (new std::ofstream{"sample.bin", std::ios::binary},// [](std::ofstream *fptr) {// fptr->close();// delete fptr;// }); // error
标签: #unique函数怎样不显示错误