使用 std::unique
Link Share :https://zhiqiang.org/coding/std-unique-ptr.html
- via RSS
理论上而言,当 C++提供了std::unique_ptr
,
C++的程序就不应该出现普通指针了。所有普通指针都可以用std::unique_ptr
代替,避免手动删除对象。
std::unique_ptr<int> x1 = new int{1};
std::unique_ptr<int[10]> x2 = new int[10]{2, 3, 4};
std::unique_ptr
是一个标准的RAII
实现,内部只维护了一个指针。因此它没有任何效率问题。
它的实现也特别简单直接。唯一的问题时,当删除原始资源时,需根据数据是单个数据还是数组,决定调用delete
还是delete[]
。这通过定义两个不同的Deleter
来实现:
template<typename _Tp>
struct default_delete {
void operator()(_Tp* __ptr) const {
delete __ptr;
}
};
template<typename _Tp>
struct default_delete<_Tp[]> {
template<typename _Up>
typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type operator()(_Up* __ptr) const {
static_assert(sizeof(_Tp)>0, "can't delete pointer to incomplete type");
delete [] __ptr;
}
};
然后再对两种情况分别定义unique_ptr
,下面只列其中一个:
template <typename _Tp, typename _Dp = default_delete<_Tp>>
class unique_ptr {
std::tuple<pointer, _Dp> _M_t;
public:
~unique_ptr() noexcept {
auto& __ptr = _M_t.get<0>();
if (__ptr != nullptr) {
_M_t.get<1>(__ptr);
_M_t.get<0>() = nullptr;
}
}
}
这里有一个很有意思的地方在std::tuple<pointer, _Dp>
。一个很自然的想法是为什么不定义成下面这样,用起来更方便:
template <typename _Tp, typename _Dp = default_delete<_Tp>>
class unique_ptr {
pointer _M_ptr;
_Dp _M_dp;
}
其原因是默认的_Dp
是一个空结构。如果按照上面这种写法,sizeof(unique_ptr)
就变成了
16。而用std::tuple
,那么sizeof(unique_ptr)
只有 8。这个差异非常大。
为确定这一点,我们可以运行下面这段测试程序:
#include <iostream>
#include <memory>
struct Empty { };
struct A {
double x;
Empty e;
};
int main() {
std::cout << sizeof(std::unique_ptr<int>) << std::endl; // 8
std::cout << sizeof(std::shared_ptr<int>) << std::endl; // 16
std::cout << sizeof(Empty) << std::endl; // 1
std::cout << sizeof(A) << std::endl; // 16
std::cout << sizeof(std::tuple<double, Empty>) << std::endl; // 8
}
其原因需要看std::tuple
的具体实现。
Tips: Until now, everytime you want to store your article, we will help you store it in Filecoin network. In the future, you can store it in Filecoin network using your own filecoin.
Support author:
Author's Filecoin address:
Or you can use Likecoin to support author: