ali*_*ice 6 c++ rvalue lvalue c++11
#include <iostream>
using namespace std;
void f(const char * const &s) {
cout << "lvalue" << endl;
}
void f(const char * const &&s) {
cout << "rvalue" << endl;
}
int main()
{
char s[] = "abc";
f("abc");
f(s);
}
Run Code Online (Sandbox Code Playgroud)
输出:
rvalue
rvalue
Run Code Online (Sandbox Code Playgroud)
为什么输出"rvalue lvalue"不是?
字符串文字也不是s指针(它们是数组),因此标准的相关部分是 [conv.array]:
“数组
NT”或“未知边界数组T”类型的左值或右值可以转换为“指向T”的指针类型的纯右值。结果是指向数组第一个元素的指针。
注意
char const *p = s;
f(p);
Run Code Online (Sandbox Code Playgroud)
打印“左值”,以表明这按照您对指针的预期工作。
附录:评论:如果
char *p = s;
f(p);
Run Code Online (Sandbox Code Playgroud)
如果右值重载存在,则打印“rvalue”,但如果删除它,则不会导致编译器错误,标准的其他两个部分开始发挥作用——其中一个似乎完全禁止绑定到char*,char const *const &另一个打开一个窗口回来。
第一个是 [dcl.init.ref]/4,其中指出
给定类型“ cv1
T1”和“ cv2T2”,如果“ cv1T1”与“ cv2 ”类型相同,或者是 的基类,则“cv1 ”与“cv2 ”引用相关。如果“ cv1 ”与“ cv2 ”引用相关,并且cv1与cv2具有相同的 cv 限定,或者比 cv2 更高,则“ cv1 ”与“ cv2 ”引用兼容。(...)T2T1T2T1T2T1T2T1T2
它详细介绍了参考初始化的精确规则,所有这些都是相关的,但不幸的是对于一个如此答案来说太长了。长话短说,如果cv1 的引用是引用兼容的,则可以使用cv2T1的对象来初始化对cv1 的引用。 T2
这种法律术语对于我们的情况意味着char*和char const *不是引用兼容的(尽管char*并且char *const将会是),因为一个char*不是char const *也不是另一个的基类。如果您认为以下非法代码段在其他情况下是合法的,则此限制是有意义的:
const char c = 'c';
char *pc;
const char*& pcc = pc; // #1: not allowed
pcc = &c;
*pc = 'C'; // #2: modifies a const object
Run Code Online (Sandbox Code Playgroud)
这是改编自 [conv.qual]/4 中的类似示例,该示例使用指向指针的指针来演示相同的问题。
[conv.qual] 也是打开窗口的其他相关部分。它在 [conv.qual]/1 中表示:
如果“ cv2 ”比“ cv1 ”更具 cv限定,则“指向cv1 的
T指针”类型的纯右值可以转换为“指向 cv2 的指针”类型的纯右值TTT
由此可知char*可以转换为char const *1(与 引用兼容),这就是为什么如果删除char const *const的右值重载,代码仍然可以编译。f但是,此转换的结果是纯右值,因此如果存在,则在重载决策中首选右值重载。
1 char*泛左值 ->char*纯右值 (by [conv.lval]) ->char const *纯右值)
| 归档时间: |
|
| 查看次数: |
705 次 |
| 最近记录: |