欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

std::move与forward

程序员文章站 2022-05-27 22:40:00
...

 

一. 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详解

 

 

 

 

 

 

 

 

 

 

相关标签: move forward