POD,右值和左值

任何人都可以用右值,左值,POD和非POD来解释细节,下面标记的第一个表达式是不正确的,而下面的第二个表达式是正确的? 在我的理解中,int()和A()应该是右值,不是吗?


struct A {};

int main()
{
  int i;
  A a;

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

  return 0;
}


Rvalues是你从表达中得到的结果(从C标准中得到的有用的简化,但没有用C ++标准表达)。 左值是“定位值”。 左值可以用作右值。 引用总是左值,即使const。

你必须注意的主要区别可以被压缩为一个项目:你不能得到一个右值的地址(再次,不是标准,而是规则的一个有用的概括)。 换句话说,如果可以的话,你无法确定一个右值的精确位置,那么你就有一个左值。 (然而,你可以绑定一个const&到右值来“修复它”,并且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)
}

除了通过编译器提供的赋值运算符外, A() = a发生类似的事情,将右值A()变成*this 。 引用标准,12.8 / 10:

如果类定义没有显式声明复制赋值运算符,则隐式声明一个。 X类的隐式声明的复制赋值运算符将具有该形式

X& X::operator=(const X&)

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

int() = 1被明确禁止,因为int没有以相同的方式实现operator =。 然而,这种类型之间的轻微差异在实践中并不重要(至少不是我发现的)。


POD表示普通旧数据,是一组需要指定使用memcpy等效于复制的集合。 非POD是你不能使用memcpy来复制的任何类型(POD自然相反,没有任何隐藏在这里),这往往是你用C ++写的最多类型。 POD或非POD不会改变上述任何一项,而且实际上是一个单独的问题。


在我的理解中,int()和A()应该是右值,不是吗?

正确的,epxression T()对于标量和用户定义类型T总是一个右值。 只要不涉及const ,表达式T()是一个可更改的右值,更精确。

涉及标量类型的赋值需要赋值运算符左侧的可修改左值。 由于int()不是左值,所以不能指定给int()

对于用户定义的类型,赋值是一个特殊的成员函数,成员函数也可以在右值被调用(见§10.10节)。 这就是为什么A().operator=(a)的格式正确。


From C ++是否对POD typedef?的值进行初始化,引用标准:

表达式T(),其中T是非数组完整对象类型或(可能是cv限定的)void类型的简单类型说明符(7.1.5.2),它创建一个指定类型的右值,该值是值-initialized

因此int()是一个右值并且不能被赋值,正如你在第一个例子中看到的那样。

A()不会是simlle-type-specifier,因此A()会产生一个左值

链接地址: http://www.djcxy.com/p/6873.html

上一篇: PODs, rvalue and lvalues

下一篇: Understanding C++