POD,非POD,右值和左值

ano*_*ous 21 c++ pod rvalue lvalue

任何人都能解释rvalues,左值,POD和非POD方面的细节,下面标记的第一个表达式不正确而下面标记的第二个表达式是否正常?根据我的理解,int()和A()都应该是rvalues,不是吗?


struct A {};

int main()
{
  int i;
  A a;

  int() = i; //Not OK (error).
  A() = a; //OK.

  return 0;
}

Run Code Online (Sandbox Code Playgroud)

小智 19

Rvalues是你从表达式得到的(一种有用的简化,取自C标准,但在C++标准中没有措辞).左值是"定位器值".左值可以用作右值.引用总是左值,即使是const.

您必须知道的主要区别可以浓缩为一个项目:您不能获取右值的地址(同样,不是标准,而是规则的有用概括).换句话说,你无法为右值确定一个精确的位置 - 如果可以,那么你就有一个左值.(但是,您可以将const和rvalue绑定到"将其固定到位",并且0x正在大幅改变规则.)

但是,用户定义类型(UDT)稍微有些特殊:如果类的接口允许,您可以将任何右值转换为左值:

struct Special {
  Special& get_lvalue() { return *this; }
};
void f() {
  // remember "Special()" is an rvalue
  Special* p = &Special().get_lvalue(); // even though you can't dereference the
  // pointer (because the object is destroyed), you still just took the address
  // of a temporary

  // note that the get_lvalue() method doesn't need to operate on a const
  // object (though that would be fine too, if the return type matched)
}
Run Code Online (Sandbox Code Playgroud)

A() = a除了通过编译器提供的赋值运算符之外,还会发生类似的事情,将rvalue A()转换为*this.引用标准,12.8/10:

如果类定义未显式声明复制赋值运算符,则会式声明一个.类X的隐式声明的复制赋值运算符将具有该表单

X& X::operator=(const X&)
Run Code Online (Sandbox Code Playgroud)

然后它继续提供更多的资格和规格,但这是重要的一点.由于这是一个成员函数,它可以在rvalues上调用,就像Special :: get_lvalue一样,就好像你已经编写A().operator=(a)而不是A() = a.

int() = 1被明令禁止,你发现了,因为整数没有运营商=以同样的方式来实现.然而,类型之间的这种轻微差异在实践中并不重要(至少不是我发现的).


POD表示普通旧数据,是指定使用memcpy等同于复制的要求集合.非POD是你不能使用memcpy复制的任何类型(与POD完全相反,这里没有任何隐藏),这往往是你用C++编写的大多数类型.作为POD或非POD不会改变上述任何一个,并且实际上是一个单独的问题.