对未向下传递的万能引用使用std::forward是否有意义?
std::forward 成员调用场景问题解答
首先给出问题对应的代码块:
template <typename Store, typename... Args> auto get(Store&& store, Args&&... args) { return store.get(std::forward<Args>(args)...) // 1 return std::forward<Store>(store).get(std::forward<Args>(args)...) // 2 }
结论
标记为//2的写法是符合完美转发语义的通用正确写法,其正确性确实和Store类的get成员函数实现有关。
具体解释
两种写法的核心差异
std::forward的核心作用是保留参数原本的值类别(左值/右值):
- 写法1中,不管传入的
store是左值还是右值,store作为函数内的具名变量本身是左值,永远会调用左值版本的get成员函数。 - 写法2通过
std::forward<Store>(store)保留了store原本的值类别,传入左值就调用左值版本的get,传入右值就调用右值版本的get。
是否需要forward的判定标准
哪怕你没有把store作为参数传递给其他函数,只是调用它的成员函数,只要Store的get成员函数存在引用限定的重载,就必须用std::forward保留值类别,否则会出现以下问题:
- 性能损失:如果右值版本的
get做了移动优化,写法1永远无法触发该优化,只能走拷贝逻辑。 - 逻辑错误:如果右值版本的
get返回的是移动后的独立对象,左值版本返回的是内部数据的引用,写法1在传入右值store时会拿到指向即将销毁的临时对象的悬垂引用,直接触发未定义行为。
如果Store的get没有做引用限定重载,只有一个普通的成员函数,那两种写法的运行结果没有差异,但写法2依然是更规范、兼容性更强的实现。
内容的提问来源于stack exchange,提问作者Grandissimo
相关产品推荐
相关产品推荐

