当实现我自己的unique_ptr
(只是为了好玩),我发现它无法通过这个测试文件来自libstdcxx
:
struct A;
struct B
{
std::unique_ptr<A> a;
};
struct A
{
B* b;
~A() { VERIFY(b->a != nullptr); }
};
void test01()
{
B b;
b.a.reset(new A);
b.a->b = &b;
}
gcc很高兴地通过了这个测试文件(当然,这个文件来自libstdcxx),而clang对于该VERIFY
部分而言却失败了。
题:
b->a != nullptr
)对于gcc很重要,否则它将没有测试文件,但我不知道它的背后是什么。与优化有关吗?我知道很多UB都是为了更好的优化。clang
(libc ++)在这一点上似乎不兼容,因为该标准指出:
~unique_ptr();
要求:表达式
get_deleter()(get())
应格式正确,行为应明确,并且不得引发异常。[ 注意:的使用default_delete
要求T
为完整类型。— 尾注 ]效果:如果
get() == nullptr
没有效果。否则get_deleter()(get())
。
因此,析构函数应该等效于get_deleter()(get())
,这意味着b->a
不能nullptr
在的析构函数之内A
(get_deleter()
由delete
指令内部调用)。
附带说明一下,clang
(libc ++)和gcc
(libstdc ++)都将nullptr
销毁时的指针设置为std::unique_ptr
,但这是gcc
析构函数:
auto& __ptr = _M_t._M_ptr();
if (__ptr != nullptr)
get_deleter()(__ptr);
__ptr = pointer();
...这是clang
(呼叫reset()
):
pointer __tmp = __ptr_.first();
__ptr_.first() = pointer();
if (__tmp)
__ptr_.second()(__tmp);
如您所见,gcc
先删除然后分配给nullptr
(pointer()
),然后clang
先分配给nullptr
(pointer()
)然后删除1。
1 pointer
是一个对应于的别名Deleter::pointer
(如果存在的话)或简称为T*
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句