3

代码如下:

struct A
{
   static int k;
   int i;
};
 
int A::k = 10;
 
A func() { A a; return a; }

我的问题是,我如何判断是否func().kfunc().i左值?如果两者都是左值/右值,我该如何测试它们?

func().k = 0; // compile ok under g++-4.4 and g++-4.6
func().i = 1; // compile ok with g++-4.4, but g++-4.4 gives an error: 
              //"using temporary as lvalue [-fpermissive]"
4

4 回答 4

4

func().k 是一个左值,而 func().i 是一个 xvalue。

您可以查看更多详细信息: FCD 中的右值和临时对象

尽管如此,测试它们是左值还是右值并不难:

#include <iostream>

struct A
{
    static int k;
    int i;
};

int A::k = 10;

A func( ){ A a; return a; }

void f (int & ) { std::cout << "int& " << std::endl; }

int main ()
{
    func().k = 0;  //ok, because func().k is an r
    f(func().k);
    func().i = 1; //compile error: "using temporary as lvalue"
    f(func().i);  //compile error because func().i is an rvalue of type ‘int’
    return 0;
}
于 2013-05-02T19:59:08.913 回答
2

“可赋值性”不是一个很好的左值测试,因为我们可以有不可变的值(例如 const 引用表达式),并且赋值可能是一个成员函数调用,可以在类类型的右值上进行。

您必须参考标准 (ISO/IEC 14882:2011)。

5.2.2/10:如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用是左值,如果结果类型是对对象类型的右值引用,则为 xvalue,否则为纯右值。

prvaluefunc()也是如此。

5.2.5/4:如果E2声明为“reference to T”类型,E1.E2则为左值;的类型E1.E2T。否则,适用以下规则之一。

  • 如果E2是静态数据成员并且类型E2T,那么E1.E2是左值;表达式指定类的命名成员。的类型E1.E2是 T`。

左值func().k也是如此。

  • 如果E2是非静态数据成员并且类型E1是“ cq1 vq1 X ”,并且类型E2是“ cq2 vq2 T ”,则表达式指定由第一个表达式指定的对象的命名成员。如果E1是左值,那么E1.E2是左值;如果E1是一个xvalue,那么E1.E2是一个xvalue;否则,它是一个prvalue。[...]

prvaluefunc().i也是如此。

于 2013-05-02T20:35:49.023 回答
2

不需要实际“测试”给定值是左值还是右值。

从词源/历史上看,左值是赋值运算符左侧的内容,右值是右侧的内容。(虽然这个定义并不完全正确。)请注意,右值可以是左值。

简单的经验法则:如果你能获取它的地址,它就是一个左值。然而,在 C++11 中存在右值引用,这让事情变得不那么简单。所以规则更像是:如果你可以使用&.

也许一些例子可以解决问题:

int a = 5; // a is an lvalue, 5 is an rvalue
int b = fun(); // fun is an rvalue
fun() = a; // illegal, can't assign to an rvalue (suppose foo returns int)

有关更多信息,请参见http://en.wikipedia.org/wiki/Value_%28computer_science%29

于 2013-05-02T19:37:01.700 回答
0

我不确定您到底想实现什么,但是当您在返回该对象的 function() 范围内分配内存时。一旦对 function() 的调用返回,该对象就会超出范围,因此它可以被编译器释放。在后期阶段,您可能会遇到很多麻烦。我认为您需要重新设计问题解决方案。

于 2013-05-02T19:27:13.650 回答