首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >rvalue引用和std::move

rvalue引用和std::move
EN

Stack Overflow用户
提问于 2012-04-20 06:51:03
回答 2查看 684关注 0票数 2

有人能解释一下为什么B不能编译,而C可以吗?我不明白为什么需要std::move,因为变量已经是一个右值ref了。

代码语言:javascript
复制
struct A {
  int x;
  A(int x=0) : x(x) {}
  A(A&& a) : x(a.x) { a.x = 0; }
};

struct B : public A {
  B() {}
  B(B&& b) : A(b) {}  // compile error with g++-4.7
};

struct C : public A {
  C() {}
  C(C&& c) : A(std::move(c)) {}  // ok, but why?
};
EN

回答 2

Stack Overflow用户

发布于 2012-04-20 07:24:22

在声明中:

代码语言:javascript
复制
B(B&& b)

参数 b使用类型: rvalue引用到B来声明。

在声明中:

代码语言:javascript
复制
A(b)

expression bB类型的左值。

左值表达式不能绑定到右值引用:特别是语句中的右值引用:

代码语言:javascript
复制
A(A&& a)

这一逻辑从语言的其他部分清晰地遵循下来。考虑这个函数:

代码语言:javascript
复制
void
f(B& b1, B b2, B&& b3)
{
   g(b1);
   g(b2);
   g(b3);
}

尽管f的参数都是用不同的类型声明的,但表达式b1b2b3都是B类型的左值表达式,因此无论g如何重载,都会调用相同的函数g

在C++11中,区分变量的声明和使用该变量所产生的表达式比以往任何时候都更加重要。并且表达式永远不会有引用类型。相反,它们的值类别恰好是: lvalue,xvalue,prvalue之一。

声明:

代码语言:javascript
复制
A(std::move(c))

是可以的,因为std::move返回一个右值引用。函数调用返回右值引用所产生的表达式具有值category: xvalue。与prvalue一起,xvalue被认为是rvalue。和C类型的右值表达式

代码语言:javascript
复制
std::move(c)

将绑定到:A(A&& a)中的右值引用参数。

我发现下面的图表(最初是由Bjarne Stroustrup发明的)非常有用:

代码语言:javascript
复制
       expression
          /  \
    glvalue  rvalue
     /  \    /  \
lvalue  xvalue  prvalue
票数 23
EN

Stack Overflow用户

发布于 2012-04-20 06:53:14

因为命名变量不是右值,即使声明了&&。如果它有一个名字,那么它就不是临时的,因此你需要使用std::move

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10237971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档