左雪菲的专栏

欢迎访问我的个人网站:http://www.hootina.org

关于std::move和std::forward

这篇文章介绍的真不错:http://www.cnblogs.com/catch/p/3507883.html

总结起来:

1. std::move是将左值变成右值减少不必要的拷贝;

2. std::forward保持一个值的左值和右值特性不变,以变传给既能接受左值又能接受右值的函数,例:

template<class TYPE, class ARG>
TYPE* acquire_obj(ARG&& arg)
{
   return new TYPE(forward<ARG>(arg));
}

3. 本质上,std::move和std::forward底层实现都是调用static_cast来进行类型转换的。所以在运行期间不会有任何额外的消耗。

4. 

在参数类型推导上,c++11 加入了如下两个原则:

原则 (1):

引用折叠原则 (reference collapsing rule),注意,以下条目中的 T 为具体类型,不是推导类型。

1)  T& & (引用的引用) 被转化成 T&.

2)T&& & (rvalue的引用)被传化成 T&.

3)  T& && (引用作rvalue) 被转化成 T&.

4)  T&& && 被转化成 T&&.

原则 (2):

对于以 rvalue reference 作为参数的模板函数,它的参数推导也有一个特殊的原则,假设函数原型为:

template<class TYPE, class ARG>
TYPE* acquire_obj(ARG&& arg);
1) 如果我们传递 lvalue 给 acquire_obj(),则 ARG 就会被推导为 ARG&,因此如下代码的第二行,acquire_obj 被推导为: TYPE* acquire_obj(ARG& &&)。

1 ARG arg;
2 acquire_obj(arg);
然后根据前面说的折叠原则,我们得到原型如下的函数: TYPE* acquire_obj(ARG&);

2) 如果我们如下这样传递 rvalue 给 acquire_obj(),则 ARG 就会被推导为 ARG。

acquire_obj(get_arg()); 
最后,模板函数实例化为原型如下的函数:TYPE* acquire_obj(ARG&&); 

综上讨论可见,原则 2 其实是有些令人讨厌的,它与一般模板函数的参数类型推导并不一致,甚至可以说有些相背(主要在于 top level cv removal principle),这些随处可见的例外增加了语言的复杂性,加大了学习和记忆的难度,是如此令人讨厌,但在 c++ 中这种现象又那么常见,真是无奈。

阅读更多
版权声明:欢迎访问我的个人网站:http://www.hootina.org https://blog.csdn.net/analogous_love/article/details/78318110
个人分类: C++11
想对作者说点什么? 我来说一句

c++11之move语义

c++11之move语义

D_Guco D_Guco

2017-03-25 19:00:10

阅读数:648

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭