设为首页 加入收藏

TOP

4.4 赋值运算符(1)
2013-10-07 16:29:19 来源: 作者: 【 】 浏览:96
Tags:4.4 运算

4.4  赋值运算符(1)

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

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

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

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

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

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

C++(www.cppentry.com)11新标准允许使用花括号括起来的初始值列表(参见2.2.1节,第43页)作为赋值语句的右侧运算对象:

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

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

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

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

赋值运算满足右结合律

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

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

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

对于多重赋值语句中的每一个对象,它的类型或者与右边对象的类型相同、或者可由右边对象的类型转换得到(参见4.11节,第159页):
 

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

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

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

赋值运算优先级较低

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

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

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

  1. int i;  
  2. // 更好的写法:条件部分表达得更加清晰  
  3. while ((i = get_value()) != 42) {  
  4.     // 其他处理……  
  5. }  
  6. 个版本的w 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.3 逻辑和关系运算符(2) 下一篇4.4 赋值运算符(2)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: