13

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

很长一段时间以来,这句话让我感到困惑的是,我不太明白数组类型的右值是什么意思。也就是说,我想不出一个类型是数组而结果是右值的表达式。我读了这个线程,它基本上问了同样的问题,接受的答案是“不,没有数组类型的右值”。我想我可能对此有矛盾。

C++03 §5.2.5 N°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,因为当他们谈到函数到指针的转换时,他们只提到了函数类型的左值(很明显没有这样的右值)。因此,他们很可能已经考虑过数组类型的右值。

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

4

2 回答 2

12

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

请注意,它是否是右值与表达式是否表示对象无关。C++03 不小心省略了说数组类型的右值表达式表示一个对象。这已由 DR#450在 C++0x 中修复。

(显然很欣赏没有这样的右值)

实际上有函数类型的右值。这些发生在由类成员访问表达式表示的非静态成员函数中

struct A { void f(); };

/* A().f is an rvalue of type "void()" */
int main() { A().f(); }
于 2010-10-30T10:13:50.130 回答
-3

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

在最新版本的草案中,您可以在 rvalue/lvalue *this 上重载函数。但是,即使那样,右值引用也不会生成被引用的右值的内容,而且我不完全确定任何编译器当前都支持这一点,而且我知道 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 立即死亡。不确定我对此的直接看法,但它肯定对右值无效。

于 2010-10-30T10:07:22.267 回答