为何std::unique_ptr的访问开销看似高于自定义结构体?
关于std::unique_ptr与自定义结构体汇编差异的疑问
测试代码
struct Ptr { int* x; }; int* custom_struct(Ptr p) { return p.x; } int* unique_ptr(std::unique_ptr<int> x) { return x.get(); }
编译生成的汇编代码
custom_struct(Ptr): mov rax, rdi ret unique_ptr(std::unique_ptr<int, std::default_delete<int> >): mov rax, QWORD PTR [rdi] ret
我原本以为std::unique_ptr的内存布局和我定义的Ptr结构体一致,想不通为什么访问std::unique_ptr时需要从内存加载(即[rdi]),而自定义结构体直接返回rdi即可——这才是我预期中unique_ptr该有的表现。
原因解释
核心差异来自函数参数的调用约定规则:
- 自定义结构体
Ptr是仅包含单个指针的平凡可复制类型,在x86-64的System V调用约定下,这类体积较小的平凡类型会直接通过寄存器(此处为rdi)传递。函数返回p.x本质就是返回整个结构体的内容(因为结构体本身等价于那个指针),所以汇编直接执行mov rax, rdi就能完成。 std::unique_ptr虽然逻辑上只持有一个指针,但它属于非平凡类型(自带自定义的移动构造、析构等特殊成员函数)。按照调用约定,非平凡类型的参数会被分配到栈上,函数收到的rdi是指向栈上该对象的指针。因此要获取其内部的指针值,必须通过[rdi]寻址到栈内存中读取。
如果把unique_ptr的参数改为传引用,就能看到和自定义结构体类似的汇编结果:
int* unique_ptr(std::unique_ptr<int>& x) { return x.get(); }
内容的提问来源于stack exchange,提问作者Cpp Beginner
相关产品推荐
相关产品推荐

