• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
有顶天の甲子园
博客园    首页    新随笔    联系   管理    订阅  订阅
【C/C++】C++11 Move, Forward

左值与右值

Lvalue:可以出现在 operator= 左边的

Rvalue:只能出现在operator= 右边的

int a = 1;
int a = b;
a = b;
a = a + b;
a + b = a;    // error,a + b 是右值

string s1 = "hello";
string s2 = "world";
s1 + s2 = s1;         // ok
string() = "world"    // ok

注意,虽然 string 等许多容器的临时对象可以被赋值,但编译器见到临时对象会认为它是右值!

int foo() { return 3; }
...
int x = foo();     // ok
int y = &foo();    // error
foo() = 3;         // error

简单地说,能取到地址的(在内存中,而不是在寄存器中)就是右值,其余都是左值。

 

Rvalue Reference 右值引用

当赋值操作的右边是右值(rvalue),左边的对象不需要特意分配内存去存放这个拷贝(copy),而可以搬移(move)右边对象的资源。

用于解决不必要的拷贝和实现完美转发(perfect forwarding)。

 

Move Semantics 移动语义

move 相当于 浅拷贝 + 打断原指针,原来的对象无法再使用。

 

STL 许多地方使用到了右值引用和 move 语义,如 vector 中的 insert() 函数

iterator insert(const_iterator pos, const value_type& x);
iterator insert(const_iterator pos, const value_type&& x)    // 接受右值引用
{ return emplace(pos, std::move(x)); }    // 将左值变量放到std::move()中,就取得了它的右值引用

 

Perfect Forwading 完美转发

一个 Unperfect Forwarding 不完美转发的例子

 1 void process(int& i) {
 2     cout << "process(int&): " << i << endl;
 3 }
 4 
 5 void process(int&& i) {
 6     cout << "process(int&&): " << i << endl;
 7 }
 8 
 9 void forward(int&& i) {
10     cout << "forward(int&&): " << i << ", ";
11     process(i);
12 }
13 
14 int main() {
15     int a = 0;
16     process(a);         // process(int&): 0 
17     process(1);         // process(int&&): 1
18     process(move(a));   // process(int&&): 0
19     forward(2);         // forward(int&&): 2, process(int&): 2
20                         // Rvalue经由forward()传给另一个函数却变为Lvalue
21                         // 原因是传递过程中它变成了named object
22     forward(move(a));   // forward(int&&): 0, process(int&): 0
23 //  forward(a);         // error, cannot bind 'int' lvalue to 'int&&'
24     return 0;
25 }

 这时需要使用 std::forward<T>(),保留参数的左/右值特性。

void forward(int&& i) {
    cout << "forward(int&&): " << i << ", ";
    process(std::forward<int>(i));
}

int main() {
    int a = 0;
    forward(2);         // forward(int&&): 2, process(int&&): 2
    forward(move(a));   // forward(int&&): 0, process(int&&): 0
    return 0;
} 

 

posted on 2018-05-29 18:06  生涯现役丶  阅读(415)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3