+=与=..+..的区别

转载自:http://www.ticmy.com/?p=285

在继续之前,来温故一点基础:

1、做基本运算(如+、-、*、/、<<、>>、>>>、~、^等),当两个操作数的类型是byte,short,char,int之一的时候,结果的类型是int;
2、做整数基本运算时,当一个操作数是long,结果是long;
3、不加任何修饰的整数字面值默认就是int类型。

下面对上面的几点举例说明:

short s1 = 1;//OK
short s2 = s1 + 1;//ERROR

上面的第一句1整形字面值,它的类型是int,为什么可以直接赋值给short呢?因为字面值都是常量,编译器能很容易的检测出它到底在不在short所能表示的值的范围内。当写成short s1 = 32768的时候,编译就知道short容不下32768了,就会报错。
而对于第二句,s1是short类型,1是int类型,结果是int类型,自然不能自动赋值给short类型的s2了,因为有潜在的高位有效值被截断的风险。可能会有人想,上面s1已经赋值了一个字面值,对于下面的s2,编译器应该也可以计算出它的值啊。如果s1是final的,确实会这样,但s1是变量,编译器是无法预测它会不会在运行期改变的,即使它可能不会改变。

再来一个,计算一年有多少毫秒,粗心的人可能这么写:

long mills = 365 * 24 * 60 * 60 * 1000;

明眼人一看就有问题了,后面的几个数字都是int类型,计算后结果还是int类型,再将其转换成long类型,等效于以下的逻辑:

int tmp = 365 * 24 * 60 * 60 * 1000;
long mills = tmp;

计算结果的时候数据已经溢出了,再将其转换成long,依然得不到正确的结果,这样的计算很常见,也很容易被人疏忽,纠正它很容易,只要指定一个数为long类型即可:

long mills = 365 * 24 * 60 * 60 * 1000L;

开始简短的正题,如下的两段代码的区别:

short s = 1;
s = s + 1;//error

short s = 1;
s += 1;//ok

第一段代码上面已经有分析了,它通不过编译;来看看第二段,首先它能通过编译,来看看编译后的字节码(javap -c 类名)是什么样的吧:

0:   iconst_1
1:   istore_1
2:   iload_1
3:   iconst_1
4:   iadd
5:   i2s
6:   istore_1

指令0,1做了short s = 1操作,指令2,3,4做了s+1的操作,第5条是关键,做了一个强制转换,将int转换为short,第6条将强制转换的结果存回变量s。
如果s是int类型呢?

int s = 1;
s += 1;//ok

对应的字节码:

0:   iconst_1
1:   istore_1
2:   iinc 1, 1

它直接等价于i++操作了,和以下代码生成的字节码是一样的:

int s = 1;
s++;

s += 2的时候,指令为iinc 1, 2,这里是没有强制转换的。

综上可以分析出(其中type为byte,short,char,int之一,value可为变量可为常量,类型可为byte,short,char,int,float,double,long):

type s = value;
s += ovalue;//ok

逻辑上等价于(说逻辑上是因为type为int的时候并不存在强制转换,但结果是相同的):

type s = value;
s = (type)(s + ovalue);
<think>我们正在讨论Vector2D类中的运算符重载。用户之前已经了解了友元函数和流运算符重载,现在他们询问的是代码`x += other.x;`在Vector2D类中的含义和使用场景。结合之前的引用,特别是引用[1]和引用[2],我们可以这样解释: 首先,`x += other.x;`出现在`operator+=`运算符重载函数中。在引用[1]中,我们有一个`Vector2D`类的成员函数`operator+=`的定义: ```cpp Vector2D& operator+=(const Vector2D& other) { x += other.x; y += other.y; return *this; } ``` 这里,`x`和`y`是当前Vector2D对象的成员变量(假设它们在类中定义为`public`或由于是成员函数可以直接访问)。`other`是另一个Vector2D对象的常量引用。 因此,`x += other.x;`的含义是:将当前向量(调用该成员函数的向量)的x分量另一个向量(`other`)的x分量相加,并将结果存储在当前向量的x分量中。同样,下一行`y += other.y;`对y分量进行相同的操作。 使用场景:这个操作符用于实现两个向量的加法赋值。例如,如果我们有两个向量`a`和`b`,执行`a += b;`后,向量`a`的每个分量(x和y)都会加上向量`b`对应的分量,即`a.x = a.x + b.x`,`a.y = a.y + b.y`。这样,`a`就变成了两个向量的和,而`b`不变。 注意:这个运算符重载返回当前对象的引用(`*this`),这是为了支持链式调用,比如`a += b += c;`(虽然不常见,但语法上允许)。 另外,在引用[2]中,我们看到了`operator+`的重载,它返回一个新的向量,而不是修改当前向量。这`operator+=`不同,后者是复合赋值运算符,会修改当前对象。 现在,用户之前还提到了友元函数。但是在这个`operator+=`的例子中,我们使用的是成员函数。这是因为对于二元运算符,如果第一个操作数是当前类的对象,通常使用成员函数重载。对于`operator+=`,第一个操作数是当前对象(即`this`),所以用成员函数很自然。 总结回答结构: 1. 解释代码`x += other.x;`的具体含义(当前对象的x分量加上另一个向量的x分量)。 2. 说明它在`operator+=`函数中的作用(实现向量加法赋值)。 3. 对比`operator+`和`operator+=`的区别(创建新对象 vs 修改当前对象)。 4. 结合引用[1]中的示例说明使用方式。 5. 解释返回引用的原因(链式调用)。 同时,根据用户要求,生成相关问题。 注意:在回答中,如果出现数学表达式,比如向量分量,可以用行内LaTeX格式,例如:`$x$分量`,但注意代码部分不用LaTeX,而是用代码块。 最后,在适当的地方添加引用标记[^1]和[^2](因为我们参考了引用[1]和引用[2]的内容)。 </think>### 代码 `x += other.x;` 在 Vector2D 类中的含义及使用场景 #### 1. **基础含义** `x += other.x;` 是 **复合赋值运算**,等效于 `x = x + other.x;`。在 `Vector2D` 类中: - `x`:当前向量对象的 $x$ 分量(私有或公有成员变量) - `other.x`:传入的另一个 `Vector2D` 对象的 $x$ 分量(通过参数 `const Vector2D& other` 访问) ```cpp Vector2D& operator+=(const Vector2D& other) { x += other.x; // 当前x分量 += 另一个向量的x分量 y += other.y; // 同理处理y分量 return *this; // 返回当前对象的引用[^1] } ``` **操作本质**:将两个向量的 $x$ 分量相加,并将结果直接存入当前对象的 $x$ 分量(原地修改,不创建新对象)[^1][^2]。 --- #### 2. **使用场景优势** ##### (1) **高效向量加法** 对比两种加法实现: ```cpp // 方式1: 使用 operator+ (创建新对象) Vector2D a(1,2), b(3,4); Vector2D c = a + b; // 调用 operator+,生成临时对象[^2] // 方式2: 使用 operator+= (原地修改) a += b; // 直接修改a,无额外开销[^1] ``` **优势**: - **零内存分配**:避免创建临时对象,适合高频计算场景(如物理引擎、图形渲染)[^1]。 - **语法简洁**:`a += b` 比 `a = a + b` 更直观且高效。 ##### (2) **支持链式操作** 因返回当前对象的引用 (`return *this;`),可连续操作: ```cpp Vector2D v(1,1); v += Vector2D(2,2) += Vector2D(3,3); // 结果:v = (1+2+3, 1+2+3) = (6,6) ``` 此特性在流式计算中广泛应用(如矩阵变换流水线)[^1]。 --- #### 3. **友元函数的关系** ##### (1) **为何选择成员函数而非友元?** 对于运算符 `+=`: - **左操作数必须是当前类对象**:`a += b` 中 `a` 是调用主体,天然匹配成员函数。 - **可直接访问私有成员**:成员函数自动拥有访问 `x`, `y` 的权限,无需友元声明[^1][^2]。 ##### (2) **对比友元函数重载 `<<`** ```cpp // 友元函数:左操作数为流对象(std::cout),非Vector2D friend std::ostream& operator<<(std::ostream& os, const Vector2D& v); ``` 而 `+=` 的左操作数为 `Vector2D` 自身,故优先用成员函数。 --- ### 关键总结 | **特性** | **`operator+=`** | **`operator+`** | |---------------------|-----------------------------------|-------------------------------| | 实现方式 | 成员函数 | 成员函数或友元函数[^2] | | 是否修改当前对象 | 是(原地修改 `x`, `y`) | 否(返回新对象) | | 内存开销 | 无临时对象 | 生成临时对象 | | 典型调用 | `a += b;` | `c = a + b;` | | 适用场景 | 高频计算、链式操作 | 需要保留原对象的场景 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值