右值,左值和引用混淆

时间:2018-12-06 16:33:26

标签: c++

我一直试图理解右值,左值和引用以及它们作为函数(方法)的返回值的用法,因此我为实践目的创建了一些小示例。

因此,首先,我想出了这段代码(在某个地方(可能在这里阅读之后),每当我为某个方法拥有“常规”(无参考)返回值时,它就被认为是右值,当我添加参考运算符登录返回值,如本例所示:

#include <iostream>

int x = 5;
int& References()
{

    return x;
}

int main()
{ 
    References() = 3;

    std::cout << x;

    getchar();
    getchar();
}

因此,在这里,函数引用在调用时返回左值,并且此代码工作得很好,但是,由于这种方法有效,我认为我可以做其他类似的事情,这就是我尝试过的事情:

#include <iostream>

int x = 5;
int References()
{

    return x;
}

int main()
{ 
    int a = References();

    std::cout << a;

    getchar();
    getchar();
}

此代码工作正常,输出为5,这意味着我已成功为变量a分配了值,这是我期望的,因为此函数返回“普通”整数,因此它是rvalue。

但是, 当我再次向函数References的返回值添加引用运算符时,它再次正常工作:

#include <iostream>

int x = 5;
int& References()
{

    return x;
}

int main()
{ 
    int a = References();

    std::cout << a;

    getchar();
    getchar();
}

因此,即使我的函数现在返回以{{value}}形式返回的int&,此代码仍然有效,并且输出仍然为5,这意味着我设法将值成功分配给变量a。这里发生了什么?任何帮助表示赞赏!

4 个答案:

答案 0 :(得分:2)

当您在表达式或赋值中使用引用时,它会评估该引用所引用的内容,而不是内存地址,我想这就是您希望看到的内容。

比较以下函数的输出:

int x = 5;
int& References()
{
    return x;
}

int *Pointer()
{
    return &x;
}


int main()
{
    std::cout << References() << std::endl;
    std::cout << Pointer() << std::endl;
    return 0; 
}

答案 1 :(得分:2)

按引用返回时,您有一个lvalue;按值返回时,您有一个prvalue。就您而言,您可以从两者中读取差异,但无法指定给prvalue,不清楚您的困惑来自何处:

int i1 = lvalue; // fine
int i2 = prvalue; // fine

但是:

lvalue = 123; // fine
prvalue = 123; // error

更接近您的情况:

int &func1();
int func2();

int i1 = func1(); // fine
int i2 = func2(); // fine

func1() = 123; // fine
func2() = 123; // error

更多信息:Value Category

答案 2 :(得分:1)

根据https://docs.microsoft.com/en-us/previous-versions/f90831hc(v=vs.140) You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it.

第三个示例与第二个示例完全相同,只是复制值。您可以从左值复制值,就像从右值复制值一样。如果您的变量的类型为int&,则您不会复制实际值,您将获得相同的引用。这可以帮助您了解:

#include <iostream>

int x = 5;
int& References()
{

    return x;
}

int main()
{ 
    int a = References();
    int& b = References();

    std::cout << a; // 5
    std::cout << b; // 5
    std::cout << x; // 5

    a = 6;
    b = 7;

    std::cout << a; // 6
    std::cout << b; // 7
    std::cout << b; // 7


    getchar();
    getchar();
}

答案 3 :(得分:1)

为进行比较:

int  n = 10;
int& r = n;
int* p = &n;

int x = n;  // copy by value
int y = r;  // copy by value, too, use the variable referenced as source
int z = *p; // copy by value third time, using variable pointed to

int& r0 = r; // copy the reference, i. e. r0 now references n as well
int* p0 = p; // copy the pointer...

n = 12;
// now x, y, z all STILL have value 10!
// r, r0, *p and *p0, in contrast, all yield 12

功能相同:

int& ref() { return n; }
int val() { return n; }

int& r1 = ref(); // copy the reference, again r1 references n!
int& r2 = val(); // INVALID!!!
// the latter is comparable to:
int& r3 = 7;     // invalid...