std::move与forward
程序员文章站
2022-05-27 22:40:12
...
一. std::move
c++11 提供了move语义,可以实现资源转移,提高系统性能。
源码实现:
/** * @brief Convert a value to an rvalue. * @param __t A thing of arbitrary type. * @return The parameter cast to an rvalue-reference to allow moving it. */ template<typename _Tp> constexpr typename std::remove_reference<_Tp>::type&& move(_Tp&& __t) noexcept { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::remove_reference<U&>::type = U 移除类型中的引用
std::remove_reference<U&&>::type = U
static_cast<T&&>(t) 将表达式t转换为T类型右值,std::move只是将参数强制转换为右值引用。
区别左值和右值的快捷方式,看是否能对表达式取地址,如能则为左值,否则为右值。
如A a = GetA(); a为左值,GetA() 为右值。
class A { public: A() { std::cout << "Constructor" << std::endl; } A(const A&) { std::cout << "Copy Constructor" << std::endl; } //A(const A&&) { std::cout << "Move Constructor" << std::endl; } ~A() { std::cout << "Destructor" << std::endl; } }; static A getA() { A a; return a; } int main() { A a = getA(); // 普通赋值 //A&& a = getA(); // 右值引用 return 0; }
添加-fno-elide-constructors 选项阻止编译器优化
$ g++ -o test test.cpp -fno-elide-constructors -std=c++11 Constructor Copy Constructor Destructor Destructor
通过右值引用,比之前少了一次拷贝构造和一次析构,原因在于右值引用绑定了右值,延长了临时右值的生存周期。
二. std::forward
源码实现:
// Forward an lvalue. template<typename _Tp> constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) noexcept { return static_cast<_Tp&&>(__t); } // Forward an rvalue. template<typename _Tp> constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type&& __t) noexcept { static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" " substituting _Tp is an lvalue reference type"); return static_cast<_Tp&&>(__t); }
完美转发内部也是执行一个cast类型转换。
void printT(int &t) { cout << "lvalue" << endl; } void printT(int &&t) { cout << "rvalue" << endl; } template<class T> void TestForward(T &&v) { printT(v); printT(std::forward<T>(v)); // 参数转发 printT(std::move(v)); // 强制转化为右值引用 } // 调用 TestForward(1);
运行程序:
lvalue
rvalue
rvalue
1为右值,调用printT(v)时变为具名变量,即为左值,参数类型发生改变,则打印lvalue。
forward会按参数原有类型转发,则打印rvalue。
三. 函数包装器
template<class Function, class... Args> inline auto FuncWrapper(Function &&f, Args&& ... args) -> decltype(f(std::forward<Args>(args)...)) { return f(std::forward<Args>(args)...); } // 调用 FuncWrapper(printT, 15);
参考链接:
std::move/forward详解
上一篇: C++ 模板妙用
下一篇: pkg-config 用法
推荐阅读
-
jsp中页面之间的跳转forward与sendRedirect的区别
-
编程杂谈——std::vector与List
的性能比较 -
-std=gnu++11 与 -std=c++11 两者有哪些区别?
-
Effective Modern C++ 条款23 理解std::move和std::forward
-
std::bind接口与实现
-
Servlet的forward与include方法
-
【转载】RVO V.S. std::move
-
SERVLET API中forward()与redirect()的区别
-
pytorch __init__、forward与__call__的用法小结
-
new与new(std::nothrow)在文件操作上内存分布上有区别吗?