函数内直接使用参数的场景是否需要用std::forward完美转发参数?
第一个push_back场景
你给出的代码存在模板参数和形参类型不匹配的问题:声明的模板参数是element_T,但函数形参用的是element_t&&,分两种情况讨论:
- 如果
element_t是当前容器类固定的元素类型,不属于push_back自身的模板参数,那么element_t&&是右值引用,不是转发引用,不需要使用std::forward。但你写的*_end = copy存在问题:有名字的右值引用本身是左值,这个调用只会触发拷贝赋值运算符,不会用到移动赋值,需要改成*_end = std::move(copy)才能正确调用移动赋值。 - 如果这里是笔误,你想实现的是接收转发引用的通用
push_back,也就是函数签名为template <typename T> void push_back(T&& value),那这里就需要用std::forward<T>(value)传递给赋值运算符,完美保留传入参数的值类别:左值参数触发拷贝赋值,右值参数触发移动赋值。
第二个emplace_back场景
你这里必须使用std::forward<ConstructorArgs>(args)...展开参数。ConstructorArgs&&... args是标准的转发引用包,直接传递args的话,所有参数都会被当作左值传给元素构造函数:
- 会丢失右值参数的移动语义,本来可以移动构造的对象会变成拷贝构造,降低性能
- 如果参数是只能移动、不能拷贝的类型(比如
std::unique_ptr),直接传args会直接编译失败,因为无法把左值的不可拷贝对象传递给构造函数
你之前的理解完全正确:赋值运算符调用、构造函数调用和普通函数调用没有本质区别,重载选择都会受参数值类别影响,所以需要通过std::forward保留原始参数的属性。
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

