c++ - += 运算符是如何在 C++ 中实现的?
问题描述
这是我一直在思考的一个问题,并且从未找到任何资源来说明这个问题的答案。事实上,它不仅适用于+=
,而且适用于其兄弟姐妹,即-=
、*=
、/=
等(当然不是==
)。
考虑这个例子,
int a = 5;
a += 4;
//this will make 'a' 9
现在考虑等价的表达式:
a = a + 4;
//This also makes 'a' 9
If+=
只是a = a + <rhs of +=>
重载 + 运算符的简写,也应该隐式重载+=
,除非以其他方式显式重载。但事实并非如此。这意味着,a += b
不会转换为a = a + b
. 但是为什么不以这种方式实施呢?就像在编译期间简单地将其转换为a = a + b
而不是将其作为运算符单独实现不是更容易吗?这也将有助于运算符重载, where a += b
, wherea
和b
are 同一类的对象不必显式重载,并且简单地重载+
就足够了?
编辑:这个答案让我的问题变得更清楚
让我用一个需要重载运算符的例子来解释我的问题:
class A {
int ivar;
public:
A() = default;
A(int par_ivar) : ivar(par_ivar) { }
A(A& a) {
this.ivar = a.ivar;
}
A(A&& a) noexcept {
this.ivar = a.ivar;
}
A operator+(const A& a) const {
A temp_a;
temp_a.ivar = this.ivar + a.ivar;
return temp_a;
}
void operator=(const A& a) {
this.ivar = a.ivar;
}
~A() = default;
};
现在,让我们看一下 2 个程序的结果:
prog1:
int main() {
A a1(2);
A a2(3);
a1 = a1 + a2; //a1.ivar = 5
return 0;
}
编2:
int main() {
A a1(2);
A a2(3);
a1 += a2; //compilation error!!
return 0;
}
即使两个程序都打算做,不,做同样的事情,一个编译并运行(希望我的重载是正确的)另一个甚至没有编译!如果 += 被简单地替换为适当的 + 和 =,我们就不会觉得需要显式重载 +=。这是有意的,还是等待添加的功能?
解决方案
运算符不是从其他生成的(C++20 中的 with/from <=> 除外):
提供operator <
不允许a > b
(这确实“逻辑上”等同于b < a
)。你必须实现所有(甚至通过重用一些)。
对于类,a += b
不是a = a + b
但对于a.operator +=(b)
或operator +=(a, b)
以同样的方式a = a + b
是a.operator=(operator +(a, b))
(或其变体)的简写
operator+
在实践中,执行fromoperator +=
比执行相反更有效。
即使用户可能会根据他们的名字期望类似的行为,它们也是常规函数。
我已经看到了一个矩阵迭代器,它++it
增加列索引而it++
增加行索引。
If
+=
只是a = a + <rhs of +=>
重载 + 运算符的简写,也应该隐式地overload +=
,除非以其他方式显式地重载。但事实并非如此。这意味着,a += b
不会转换为a = a + b
.
(可能)不产生的理性可能是性能和控制:
向量(用于数学)或矩阵是很好的例子:
4 种可能的过载
Matrix operator+(Matrix&& lhs, Matrix&& rhs) { return std::move(lhs += rhs); }
Matrix operator+(Matrix&& lhs, const Matrix& rhs) { return std::move(lhs += rhs); }
Matrix operator+(const Matrix& lhs, Matrix&& rhs) { return std::move(rhs += lhs); } // + is symmetrical :)
Matrix operator+(const Matrix& lhs, const Matrix& rhs) { auto tmp{lhs}; return tmp += rhs; }
该决定的副作用允许给运算符赋予不同的含义,如“名称运算符”:
if (42 <in> std::vector{4, 8, 15, 16, 23, 42})
推荐阅读
- gwt - 为什么 gwt rpc 强名称不会在每个请求中更新?每个请求都是静态的吗?
- javascript - 在服务器中每 25 秒运行一次 javascript 并插入到 sql 数据库中
- fscheck - 如何使用重播在 FsCheck 上运行特定测试?
- r - lmer 因 na.pass 而失败
- outliers - 用于异常值检测的上下外栅栏
- sql - 如何仅获取列中负值的总和?
- python - 如何解决“XLRDError:不支持的格式,或损坏的文件:预期的 BOF 记录”错误?
- tensorflow - 基于 TensorFlow 中的状态限制 RL 动作空间
- python - PyMongo 清除嵌套数组中的数组
- .net - 从 ASP.NET 核心 Web 应用程序打印 PDF 文档