Skip to content

Latest commit

 

History

History
81 lines (60 loc) · 2.18 KB

File metadata and controls

81 lines (60 loc) · 2.18 KB
title unique_ptr的缺陷
date 2020-09-01 12:30
author mq

unique_ptr的缺陷

unique_ptr 不能被优化为裸指针

  • 尽管sizeof(unique_ptr<T, default_delete<T>>) == sizeof(void*), ABI 限制了 unique_ptr 不能被寄存器传递, 而是传递 unique_ptr 的地址作为参数
#include <memory>

void func(std::unique_ptr<int>& a) {
    *a = 2;
}
  • MSVC汇编输出

    a$ = 8
    void func(std::unique_ptr<int,std::default_delete<int> > &) PROC ; func, COMDAT
            mov     rax, QWORD PTR [rcx]
            mov     DWORD PTR [rax], 2
            ret     0
    void func(std::unique_ptr<int,std::default_delete<int> > &) ENDP ; func
  • clang汇编输出

    func(std::unique_ptr<int, std::default_delete<int> >&): # @func(std::unique_ptr<int, std::default_delete<int> >&)
            mov     rax, qword ptr [rdi]
            mov     dword ptr [rax], 2
            ret

均可以观察到两次内存地址mov

而裸指针

void func(int* a) {
    *a = 2;
}
  • MSVC

    a$ = 8
    void func(int *) PROC                             ; func, COMDAT
            mov     DWORD PTR [rcx], 2
            ret     0
    void func(int *) ENDP                             ; func
  • clang

    func(int*):                              # @func(int*)
            mov     dword ptr [rdi], 2
            ret

unique_ptr 不是 trivially movable

vector<unique_ptr<T>>扩容时,vector调用了for循环依此move原buffer中的对象到新buffer,而不是memcpy

当然这也怪C++没有destructive move语义,如果有的话,unique_ptr应当是"trivially destructive movable"

当API需要传递T*[](裸指针的数组)时,vector<unique_ptr<T>> 就sb了

vector的data()是unique_ptr<T>*,不是T**,除非你reinterpret_cast

(不过话说回来,non-strict-aliasing也是ABI的一部分)

non-trivial的dtor可能会影响尾调用优化

众所周知,有non-trivial析构对象的函数的尾调用不是尾调用

(吱又要喷我了,我不懂PTC,哪位巨巨给补充一下)