c++ - 为什么运算符重载上的 ref-qualifier 和 cv-qualifier 允许右值赋值?
问题描述
向运算符添加 ref 限定符将消除进行右值赋值的可能性
例如,用g++ -std=c++14 bar.cpp && ./a.out
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
};
int main()
{
foo() += 10;
}
会给你
$ g++ -std=c++14 bar.cpp && ./a.out
bar.cpp: In function ‘int main()’:
bar.cpp:14:14: error: passing ‘foo’ as ‘this’ argument discards qualifiers [-fpermissive]
14 | foo() += 10;
| ^~
bar.cpp:6:10: note: in call to ‘void foo::operator+=(int) &’
6 | void operator+=(int x) & { printf("%d\n", x+2); }
| ^~~~~~~~
您当然可以通过添加显式来“解决”这个问题&&
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) && { printf("%d\n", x+3); }
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
13
但是添加 aconst &
也会让你调用+=
结构实例。
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) const & { printf("%d\n", x+4); }
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
14
要“解决”这个问题,const &&
必须明确删除
#include <cstdio>
struct foo
{
void operator+=(int x) & { printf("%d\n", x+2); }
void operator+=(int x) const & { printf("%d\n", x+4); }
void operator+=(int x) const && = delete;
};
int main()
{
foo() += 10;
}
输出
$ g++ -std=c++14 bar.cpp && ./a.out
bar.cpp: In function ‘int main()’:
bar.cpp:14:14: error: use of deleted function ‘void foo::operator+=(int) const &&’
14 | foo() += 10;
| ^~
bar.cpp:9:10: note: declared here
9 | void operator+=(int x) const && = delete;
| ^~~~~~~~
为什么是这样?为什么添加 ref-qualifier 会隐式删除右值分配?但是将 cv 限定符与 ref 限定符一起添加似乎隐式添加了右值赋值?
我确定我在这里遗漏了一些明显的东西。但是 Google-Wan Kenobi 似乎无法帮助我理解。
解决方案
因为右值可以绑定到左值引用到const
. 和下面的代码一样:
foo& r1 = foo(); // invalid; rvalues can't be bound to lvalue-reference to non-const
const foo& r2 = foo(); // fine; rvalues can be bound to lvalue-reference to const
顺便说一句:当调用右值时,用右值引用限定的重载在重载决议中获胜。这就是为什么您将其标记为delete
明确按预期工作的原因。
推荐阅读
- python - 在 ssh 终端上收听击键
- api - 如何保护烧瓶 api?
- spring-boot - javax.mail.AuthenticationFailedException [AUTH] 需要 Web 登录:https://support.google.com/mail/answer/78754
- javascript - 将字符串下载为文本文件
- node.js - 为什么 ESlint 显示 Unable to resolve path to module 错误?
- python - 关系“app_model”不存在第 1 行:SELECT COUNT(*) AS “__count” FROM “app_model”
- setuptools - 如何在 setup.py 和应用程序代码之间共享包元数据?
- python - 如何将列表过滤为三个子列表?
- android - Android 日历 - 查询 Instances 表并不总是返回新数据
- javascript - URL() 构造函数在 chrome 的主机中添加 %20,但在 Firefox 中无效