为什么 const 函数 returns 是左值而不是右值?

why the const function returns lvalue rather than rvalue?

ff() 函数 return 是右值,但是当我将函数的 return 值更改为 const 时,它是 return 左值吗?为什么当我将 test ff() { } 更改为 const test ff() { }

时,以下输出将其输出从 "lvalue reference" 更改为 "rvalue reference"
#include <iostream>
using namespace std;
class test { };
void fun( const test& a)
{
    cout << "lvalue reference"<<endl;
}
void fun(  test&& a)
{
    cout << "rvalue reference"<<endl;
}
const test ff() { } // <<---return value is const now
int main()
{

  fun(ff());
}     

输出:

lvalue reference

void fun( test&& a) 是一个引用非常量右值的函数。 ff returns a const test 这是一个 const rvalue。您不能将对非 const 右值的引用绑定到 const 右值,因为那样会违反 const 正确性。这就是它绑定到 void fun( const test& a) 的原因,它引用了 const test


请注意,当 return 按值计算时,return const thingthing 没有任何优势。唯一一次将 const 添加到 return 类型很重要是当 returning 通过引用时。如果您有一个标记为 const 或 return 引用常量数据成员的成员函数,那么您必须使用 const 来保持常量正确性。

您的测试函数输出具有误导性,测试函数应该改为:

void fun( const test& a)
{
    cout << "lvalue const reference"<<endl;
}
void fun( test& a)
{
    cout << "lvalue reference"<<endl;
}
void fun(  test&& a)
{
    cout << "rvalue reference"<<endl;
}
void fun( const test&& a)
{
    cout << "rvalue const reference"<<endl;
}

然后你就会看到那里到底发生了什么。

在这种情况下,如果您对编译器选择一个重载而不是另一个重载感兴趣,通常最简单的方法(或多或少)直接询问编译器 how/why 它做出了它所做的决定,只允许它 select 另一个函数,并查看它给出的错误消息(或者它是否可能根本不给出错误消息)。在这种情况下,我们可以删除采用 const 左值引用的函数来获得如下代码:

#include <iostream>
using namespace std;
class test { };
// void fun( const test& a)
// {
//     cout << "lvalue reference"<<endl;
// }
void fun(  test&& a)
{
    cout << "rvalue reference"<<endl;
}
const test ff() { } // <<---return value is const now
int main()
{

  fun(ff());
}

现在如果我们尝试编译,编译器会直接告诉我们为什么剩下的函数没有被 selected:

trash9.cpp:16:3: error: no matching function for call to 'fun'
  fun(ff());
  ^~~
trash9.cpp:8:6: note: candidate function not viable: 1st argument ('const test') would lose const qualifier
void fun(  test&& a)
     ^

这不像直接引用标准那样权威,但编译器在处理此类事情方面做得足够好,因此错误消息可以提供相当多的信息。