C++中以const引用传递指针而非值传递有哪些实际应用场景?
const&传递的适用场景讨论 由于引用(some-type&)的行为与常量指针(some-type * const)一致,使用「指针的常量引用」作为形参(即some-type * const&)传递参数乍看有些冗余,我们可以先对比它和普通指针值传递的行为差异:
- 形参类型为
some-type *(指针值传递)- 传参时会生成指针的拷贝
- 函数内部操作的是独立的指针副本,无法修改调用方传入的原始指针
- 形参类型为
some-type * const&(指针常量引用传递)- 传参时不会生成指针拷贝
- 函数内部持有的是
const限定的引用实体,同样无法修改调用方传入的原始指针
单从对外行为来看,两种传参方式的效果完全一致,唯一的区别仅在于值传递会产生拷贝开销,引用传递不会。
这份拷贝开销差异对std::shared_ptr来说影响相对明显:它的体积通常大于原生指针和std::unique_ptr,拷贝时除了复制指针本身的内存,还会触发引用计数的原子操作,整体开销比拷贝普通指针高不少。
这就引出了一个常见疑问:为了避免拷贝开销而对大体积的std::shared_ptr使用const&传递,是不是指针参数采用const&传递的唯一适用场景?
针对「指针类型不需要单独讨论,直接套用普通类型的传参规则即可」的看法,我们可以先梳理两类类型的传参逻辑差异:
对于非指针类的普通数据类型,值传递与const&传递的选择逻辑非常明确:两种方式都不会修改调用方的原始实体,const&的核心优势是可以避免大体积对象的拷贝开销,小体积对象直接值传递效率更高。
对于原生指针、智能指针这类指针类实体,通常认为它们的体积都很小(和普通基础类型相当),只有部分实现下的std::shared_ptr可能体积更大、拷贝成本更高。
那么问题进一步细化:当我们处理体积明显很小的原生指针、std::unique_ptr,以及小体积实现的std::shared_ptr时,const&传递能节省的拷贝开销几乎可以忽略不计,这种情况下是否还有其他理由要选择以const&形式传递这类指针?
内容的提问来源于stack exchange,提问作者Enlico

