为什么 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 thing
比 thing
没有任何优势。唯一一次将 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)
^
这不像直接引用标准那样权威,但编译器在处理此类事情方面做得足够好,因此错误消息可以提供相当多的信息。
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 thing
比 thing
没有任何优势。唯一一次将 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)
^
这不像直接引用标准那样权威,但编译器在处理此类事情方面做得足够好,因此错误消息可以提供相当多的信息。