2010-10-30 60 views
11

C++ 03§4.2N°1:
左值或类型的右值“阵列NT的”或“的阵列T的未知边界“可以转换为类型为”指向T的指针“的右值。结果是指向数组的第一个元素的指针。我想可能想出了阵列型的右值的一个例子

很长时间以来,我一直在困惑的是,我并不完全理解数组类型的右值意味着什么。也就是说,我无法想出一个表达式,其类型是一个数组,结果是一个右值。我读this线程,它基本上提出相同的问题,并且接受的答案是“不,数组类型不存在右值”。我想我可能会对此产生矛盾。

C++ 03§5.2.5N°4:(约为表达E1.E2)
如果E2是一个非静态数据成员,和E1的类型是“CQ1 VQ1 X“,并且E2的类型是”cq2 vq2 T“,该表达式指定由第一个表达式指定的对象的指定成员。如果E1是一个左值,那么E1.E2是一个左值。

我认为否则它是一个右值(E2提供的是不是一个参考,这种情况下,由§5.2.5 N°3覆盖),因此...

struct A 
{ 
    int a[4]; 
}; 
A f() 
{ 
    A a; 
    return a; 
} 
int main() 
{ 
    f().a; //I think this is an rvalue of array type... 
} 

在这里我看到两个选项:
选项1:我是对的,欢呼,好,很酷。在这种情况下,问题是:还有其他例子吗?
选项2:我错了,在这种情况下,问题是:这是标准的缺陷吗?

我不知道1,但我真的怀疑2,因为当他们谈论函数到指针的转换时,他们只提到了函数类型的左值(显然理解这里没有右值)。所以他们很可能会想到数组类型的右值。

所以,基本上我的问题是我是否没有拿出数组类型的右值的一个例子,如果没有,请提供一个有效的,我相信stongly存在。

回答

11

是的,你是对的。该表达式是数组类型的右值。这不是一个缺陷 - 委员会知道它,它也是C89中的一个常见问题,它只允许转换为数组类型左值的指针。因此,您无法索引或取消引用像f().a这样的数组。 C99解决了这个问题,并且C++没有问题。

请注意,无论它是否是右值都与表达式是否表示对象无关。 C++ 03意外地忽略了一个数组类型的右值表达式表示一个对象。这在C++ 0x by DR#450中修复。

(明显升值,有没有这样的右值)

其实有函数类型的右值。这些出现在由类成员表示的非静态成员函数中访问表达式

struct A { void f(); }; 

/* A().f is an rvalue of type "void()" */ 
int main() { A().f(); } 
+0

谢谢!所以你知道这是否是右值数组的唯一情况,这是由。或 - >。还有其他的例子吗? – 2010-10-30 10:23:21

+0

@Armen我想不出另一种情况(对于C++ 03)。 – 2010-10-30 10:27:16

+1

@Armen注意到,因此,即使将数组声明为const const a [4];',Comeau也表示'A()。a'的类型为int [4]'。这是因为该标准表示非类类型的rvalues从来没有cv限定,并且因为EDG前端对数组及其元素类型进行cv限定为双向等效(请参阅核心问题#1059)。 – 2010-10-30 10:32:31

-3

的A是一个rvalue。它里面的数组不是。想象一下你在那个临时对象上有一个方法链的情况 - 它内部的变量存在多于一个方法调用和返回,并且它们可以将引用(对于链的持续时间有效)传递给其他函数。这些功能不能预先知道它们应该被称为右值。

在草案的最新版本,您可以在右值/左值*此超载功能。但是,即使如此,右值引用并不会使所引用的右值的内容成为可能,并且我不完全确定ANY编译器目前是否支持此值,并且我知道MSVC不支持此值。

逸岸,使用decltype,和您可以轻松确定编译器调用数组左值。

考虑:

template<typename A, typename B> auto sum(A&& a, B&& b) -> decltype(std::forward<A>(a) + std::forward<B>(b)) { 
    return std::forward<A>(a) + std::forward<B>(b); 
} 

这就是decltype是因为,它左值和右值之间最肯定的区别。或者,考虑这一点:

int main() 
{ 
    auto var = f().a; 
} 

var是int *。这是一个瞬间失败,因为f()。a立即死亡。我不确定我的立即意见,但它肯定对一个右值无效。

+0

decltype不区分rvalues和lvalues。并请再次阅读我的第二次报价。 – 2010-10-30 10:17:22

+0

@阿门:decltype的全部点是区分。如果完美的转发甚至开始工作,还有什么可能呢 – Puppy 2010-10-30 10:42:47

+2

@DeadMG decltype(expr)是expr的类型。 expr是否是左值还是右值与它的类型无关。 – 2010-10-30 10:44:16

相关问题