在这种情况下如何测试左值或右值

How to test lvalue or rvalue in this case

本文关键字:测试 这种情况下 何测试      更新时间:2023-10-16

代码如下:

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]"

func()。K是一个左值和函数。I是一个x值。

你可以看到更多的细节: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;
}

可分配性"不是左值的好测试,因为我们可以有不可变的左值(例如const引用表达式),并且赋值可以是可以对类类型的右值进行的成员函数调用。

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

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

所以func()右值

5.2.5/4:如果声明E2类型"引用T",则";则E1.E2为左值;E1.E2的类型为T。否则,应用下列规则之一:

  • 如果E2为静态数据成员,E2的类型为T,则E1.E2为左值;表达式指定类的命名成员。E1.E2的类型为T ' .

所以func().k左值

  • 如果E2为非静态数据成员,E1的类型为";cq1 vq1 X &",E2的类型为";cq2 vq2 T &",则表达式指定第一个表达式指定的对象的命名成员。如果E1为左值,则E1.E2为左值;如果E1为xvalue,则E1.E2为xvalue;否则,它是一个右值。[…]

所以func().iprvalue

实际上不需要"测试"给定的值是左值还是右值。

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

简单的经验法则:如果你能获取它的地址,它就是一个左值。然而,在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)

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