`
tcspecial
  • 浏览: 906486 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

std::move与forward

阅读更多

 

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

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics