C++Primer 赋值运算符

news/2025/2/7 6:30:58/

欢迎阅读我的 【C++Primer】专栏

专栏简介:本专栏主要面向C++初学者,解释C++的一些基本概念和基础语言特性,涉及C++标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级程序设计技术。希望对读者有帮助!

在这里插入图片描述
在这里插入图片描述

目录

  • 4.4 赋值运算符
    • 赋值运算满足右结合律
    • 赋值运算优先级较低
    • 切勿混淆相等运算符和赋值运算符
    • 复合赋值运算符

4.4 赋值运算符

赋值运算符的左侧运算对象必须是一个可修改的左值。如果给定

int i= 0,j=0,k=0; //初始化而非赋值
const int ci = i; // 初始化而非赋值

则下面的赋值语句都是非法的:

1024 = k//错误;字面值是右值
i+j = k;// 错误:算术表达式是右值
ci  = k;//错误:ci是常量(不可修改的)左值

赋值运算的结果是它的左侧运算对象,并且是一个左值。相应的,结果的类型就是左侧运算对象的类型。如果赋值运算符的左右两个运算对象类型不同,则右侧运算对象将转换成左侧运算对象的类型:

k = 0;       //结果:类型是int,值是0
k = 3.14159; //结果:类型是int,值是3

C++11新标准允许使用花括号括起来的初始值列表,作为赋值语句的右侧运算对象:

k = {3.14};  //错误:窄化转换
vector<int> vi;//初始为空
vi = {0,1,2,3,4;5,6,7,8,9}; //vi现在有10个元素了,值从0到9

如果左侧运算对象是内置类型,那么初始值列表最多只能包含一个值,而且该值即使转换的话其所占空间也不应该大于目标类型的空间。

对于类类型来说,赋值运算的细节由类本身决定。对于vector来说,vector模板重载了赋值运算符并且可以接收初始值列表,当赋值发生时用右侧运算对象的元素茵换左侧运算对象的元素。

无论左侧运算对象的类型是什么,初始值列表都可以为空。此时,编译器创建一个值初始化的临时量并将其赋给左侧运算对象。

赋值运算满足右结合律

赋值运算符满足右结合律,这一点与其他二元运算符不太一样:

int ival,jval;
ival=jval=0;//正确:都被赋值为0

因为赋值运算符满足右结合律,所以靠右的赋值运算jval=0作为靠左的赋值运算符的右侧运算对象。又因为赋值运算返回的是其左侧运算对象,所以靠右的赋值运算的结果(即jval)被赋给了ival。

对于多重赋值语句中的每一个对象,它的类型或者与右边对象的类型相同、或者可由右边对象的类型转换得到:

int ival,*pval;  //ival的类型是int; pval是指向int的指针
ival = pval = 0; //错误:不能把指针的值赋给int
string s1,s2;
s1 =s2 = "OK";   //字符串字面值“OK“转换成string对象

因为ival和pval的类型不同,而且pval的类型(int*)无法转换成ival的类型(int),所以尽管0这个值能赋给任何对象,但是第一条赋值语句仍然是非法的。

与之相反,第二条赋值语句是合法的。这是因为字符串字面值可以转换成string对象并赋给s2,而s2和s1的类型相同,所以s2的值可以继续赋给s1。

赋值运算优先级较低

赋值语句经常会出现在条件当中。因为赋值运算的优先级相对较低,所以通常需要给赋值部分加上括号使其符合我们的原意。下面这个循环说明了把赋值语句放在条件当中有什么用处,它的目的是反复调用一个函数直到返回期望的值(比如42)为止:

//这是一种形式烦琐、容易出错的写法
int i=get_value(); //得到第一个值
while(i!=42)
{// 其他处理...i = get_value();  //得到剩下的值
}

在这段代码中,首先调用get_value函数得到一个值,然后循环部分使用该值作为条件。在循环体内部,最后一条语句会再次调用getvalue函数并不断重复循环。可以将上述代码以更简单直接的形式表达出来:

int i;//更好的写法:条件部分表达得更加清晰
while((i=get_value())!=42)//其他处理…...

这个版本的while条件更容易表达我们的真实意图:不断循环读取数据直至遇到42为止。其处理过程是首先将get_value函数的返回值赋给i,然后比较i和42是否相等。

如果不加括号的话含义会有很大变化,比较运算符!=的运算对象将是get_value函数的返回值及42,比较的结果不论真假将以布尔值的形式赋值给,这显然不是我们期望的结果。

切勿混淆相等运算符和赋值运算符

C++语言允许用赋值运算作为条件,但是这一特性可能带来意想不到的后果:

if(i = j)

此时,if语句的条件部分把j的值赋给i,然后检查赋值的结果是否为真。如果j不为0,条件将为真。然而程序员的初衷很可能是想判断i和j是否相等:

if(i==j)

程序的这种缺陷显然很难被发现,好在一部分编译器会对类似的代码给出警告信息。

复合赋值运算符

我们经常需要对对象施以某种运算,然后把计算的结果再赋给该对象。举个例子,求和程序:

int sum = 0
//计算从1到10(包含10在内)的和
for(int val=1;val<=10;++val)sum+=val//等价于 sum = sum + val;

这种复合操作不仅对加法来说很常见,而且也常常应用于其他算术运算符或者位运算符。每种运算符都有相应的复合赋值形式:

+= -= *= /= ;%= //算术运算符<<= >>= &= ^= |= //位运算符

任意一种复合运算符都完全等价于

a = a op b;

唯一的区别是左侧运算对象的求值次数:使用复合运算符只求值一次,使用普通的运算符则求值两次。这两次包括:一次是作为右边子表达式的一部分求值,另一次是作为赋值运算的左侧运算对象求值。其实在很多地方,这种区别除了对程序性能有些许影响外几乎可以忽略不计。


http://www.ppmy.cn/news/1570002.html

相关文章

自动驾驶---两轮自行车的自主导航

1 背景 无人驾驶汽车最早出现在DARPA的比赛中&#xff0c;从那个时刻开始&#xff0c;逐渐引起全球学者的注意&#xff0c;于是从上个世纪开始各大高校院所开始了无人汽车的研发。直到这两年&#xff0c;无人驾驶汽车才开始走进寻常百姓家&#xff0c;虽然目前市面上的乘用车还…

C语言数据结构编程练习-排序算法

1、冒泡排序 思路&#xff1a;比较相邻的两个数&#xff0c;左边大于右边交换一趟排下来最大的在右边时间复杂度&#xff1a;O(n2) //冒泡排序 从小到大的顺序排列 //思路&#xff1a;比较相邻的两个数&#xff0c;左边大于右边交换一趟排下来最大的在右边 void bubbleSort(i…

LabVIEW图片识别逆向建模系统

本文介绍了一个基于LabVIEW的图片识别逆向建模系统的开发过程。系统利用LabVIEW的强大视觉处理功能&#xff0c;通过二维图片快速生成对应的三维模型&#xff0c;不仅降低了逆向建模的技术门槛&#xff0c;还大幅提升了建模效率。 ​ 项目背景 在传统的逆向建模过程中&#xf…

BOOST开关调整器拓扑

电路原理 在V和开关管Q1之间串接电感L1。当Q1导通时,电流从电感L1的下端流入 Q1。当 Q1关断时,电流从电感L1的下端通过整流二极管D1输送给输出电容C。及负载。 假设输出电压和电流已建立,电路已稳定运行,当Q1导通时(Tm),二极管反偏截止,L1的电流线性上升达到峰值l。 V T„/L1…

C++中常用的十大排序方法之4——希尔排序

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C中常用的排序方法之4——希尔排序的相…

计算机网络笔记再战——理解几个经典的协议5——围绕IP的几个辅助协议

目录 DNS DNS查询 ARP ICMP DHCP NAT DNS 没人喜欢天天背诵&#xff0c;输入一场串IP&#xff01;我们需要一个稍微有含义一点的名称——比如说www.google.com来标记我访问的是谷歌&#xff0c;而不是一大长串的IP地址&#xff01;域名服务解析就是一个完成这样的功能的一…

计算机网络网络层进阶:NAT、ARP 与 IP 系列技术全析!!!

一、网络地址转换NAT 私有IP 地址(内网IP)&#xff1a; 10.0.0.0~10.255.255.255 172.16.0.0~172.31.255.255 192.168.0.0~192.168.255.255 只允许分配给局域网内部的节点,不允许分配给互联网上的节点每个局域网内部都可以自行分配这些私有 IP 地址私有 IP 地址是可复用的&…

深入解析:如何利用 Python 爬虫获取商品 SKU 详细信息

在电商领域&#xff0c;SKU&#xff08;Stock Keeping Unit&#xff0c;库存单位&#xff09;详细信息是电商运营的核心数据之一。它不仅包含了商品的规格、价格、库存等关键信息&#xff0c;还直接影响到库存管理、价格策略和市场分析等多个方面。本文将详细介绍如何利用 Pyth…