| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1462 人关注过本帖
标题:关于递增操作符(++)的一些讨论
只看楼主 加入收藏
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
结帖率:96.55%
收藏
 问题点数:0 回复次数:9 
关于递增操作符(++)的一些讨论
    在讨论递增操作符之前先说明几个概念,之后会用到。
    1、顺序点:程序执行过程中的一个点。在这里,进入下一步之前将确保对所有的副作用都进行了评估。在C++中,语句中的分号就是一个顺序点,这意味着程序处理下一句语句之前,赋值操作符、递增操作符和递减操作符等执行的修改都必须完成。另外,任何完整表达式末尾都是一个顺序点。
    2、副作用:在计算表达式时对某些东西(如存储在变量中的值)进行了修改,这种现象称为该表达式具有副作用。
    3、完整表达式:它是这样一个表达式,不是另一个更大表达式的子表达式。完整表达式的例子有:表达式语句中的表达式部分以及用作while循环中的检测条件的表达式。
    下面正式讨论一下递增操作符:
    1、递增操作符有两个版本:前缀版本和后缀版本。
    2、前缀递增操作符、前缀递减操作符和解除引用操作符的优先级相同,都以从右往左的方式进行结合。后缀递增操作符、后缀递减操作符的优先级相同,但比前缀版本的操作符的优先级高,这两个操作符以从左往右的方式进行结合。
    3、对于一个语句中各表达式均使用完整表达式时,使用递增操作符的前缀版本和后缀版本,两者的最终效果在数值方面没有任何区别。表达式的值未被使用,因此只存在副作用。但是两者的执行速度可能有细微的差别。对于内置类型和当代编译器而言,这看似不是什么   问题。然而C++允许程序员针对类定义这些操作符。对于后缀版本首先复制一个拷贝,将其加1,然后将复制的拷贝返回。因此,前缀版本的效率比后缀版本的效率要高。
    4、在语句
           while (guests++ < 10)
               cout << guests;
       中表达式guests++ < 10 是一条完整表达式,因为它是一个while循环的测试条件,因此该表达式的末尾是一个顺序点。所以,C++确保副作用(将guests加1)在程序进入cout << guests之前完成。然后通过递增操作符后缀版本,可确保将guests同10进行比较后再将其值加1.
在语句
           y = (4 + x++) + (6 + x++);
       中表达式 4 + x++ 不是一个完整表达式。因此,C++不保证x的值在计算子表达式 4 + x++ 后立刻增加1。在这个语句中,整条赋值语句时一个完整表达式,而分号标示了顺序点,因此C++只保证程序执行到下一条语句之前,x的值将被递增两次。C++没有规定是在计算每个子表达式之后将x的值递增,还是在整个表达式计算完毕后才将x的值递增。

这些东西是本人自己通过查阅一些材料,自己总结的。如果有人发现有错误请后面跟帖说明。
希望看到这个贴的朋友,可以加入QQ群125978818,这个群主要针对C++初学者。在群中,我会不定期上传类似文章和大家一起讨论。
搜索更多相关主题的帖子: 操作符 递增 
2010-12-06 01:01
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:0 
程序代码:
#include <iostream>
using namespace std;
class A
{
private:
    int a;
public:
    A();
    ~A();
    void DisPlay();
    int  operator++();
};
void A::DisPlay()
{
    cout<<a<<endl;
}
A::A()
{
    a=5;
}
A::~A()
{
    ;
}
int A::operator ++()
{
    int temp;
    temp=this->a;
    a+=1;
    return temp;
}
int main()
{
    A a1;
    a1.DisPlay();
    cout<<a1++<<endl;
    a1.DisPlay();
    return 0;
}
呵呵 其实你知道++运算符重载函数 怎么实现的就可以了

                                         
===========深入<----------------->浅出============
2010-12-06 10:40
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
收藏
得分:0 
我不是想告诉大家++操作符时如何重载的,而是想告诉大家++操作符在平时使用的时候应该注意些什么
2010-12-06 19:21
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:0 
嗯,这个帖子讲得很深刻。很多概念不是属于入门知识,适合有一定基础的人进阶看看。可以看出楼主下了不少功夫~~


不过关于 y = (4 + x++) + (6 + x++);  这个語句,我有几点补充。
当然楼主也表明,这个語句本身有些毛病,不过这个毛病有点比楼主指出的要大。(我这是吹毛求疵,一般只有语言律师会这么咬文嚼字。)

标准第五章引论的第四条(见下5-4)里说了“(我翻译一下)除非特别注明,对诸如运算符的运算以及表达式的子表达式的评估(evaluation)顺序、副作用的发生顺序是未明确(unspecified)的。在前后两个顺序点之间评估一个表达式时,对一个纯量对象(scalar object)储存值的改动至多出现一次。此外,对该对象原来值的访问应仅是为了确定其新值。对所有容许顺序推定的完全表达式的子表达式,本条目的规定均生效。违反的表达式的行为是未定义(undefined)的。”

关于“未明确”和“未定义”的概念,是在第一章第九节(见 1.9.3 和 1.9.4)中描述的,1.9.4 中指出“(我还是翻译一下)在本国际标准中某些操作被描述为未定义(例如,对空指针(null pointer)的解引用(dereferencing))[注:本国际标准对含有未定义行为的程序的行为不施加任何限制。]”

由此可见,那个語句,在两个顺序点之间,对 x 的值修改了两次。因此是未定义的。楼主说 “C++会保证程序执行到下一条语句之前,将 x 的值递增两次”,其实这个标准保证不了。编译器对这个語句做任何处理,都是符合标准的(因为标准没有任何限制)。


下面援引标准上的一些原文,以帮助大家深入学习(包括楼主介绍的一些概念,这个只有原文才够权威~~):
1.9.3:Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified (for example, order of evaluation of arguments to a function). Where possible, this International Standard defines a set of allowable behaviors. These define the nondeterministic aspects of the abstract machine. An instance of the abstract machine can thus have more than one possible execution sequence for a given program and a given input.

1.9.4: Certain other operations are described in this International Standard as undefined (for example, the effect of dereferencing the null pointer). [Note: this International Standard imposes no requirements on the behavior of programs that contain undefined behavior. ]

1.9.7: Accessing an object designated by a volatile lvalue (3.10), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression might produce side effects. At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.

1.9.11-1: At sequence points, volatile objects are stable in the sense that previous evaluations are complete and subsequent evaluations have not yet occurred.

1.9.12: A full-expression is an expression that is not a subexpression of another expression. If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition.

1.9.13: [Note: certain contexts in C++ cause the evaluation of a full-expression that results from a syntactic construct other than expression (5.18). For example, in 8.5 one syntax for initializer is
    ( expression-list )
but the resulting construct is a function call upon a constructor function with expression-list as an argument list; such a function call is a full-expression. For example, in 8.5, another syntax for initializer is
    = initializer-clause
but again the resulting construct might be a function call upon a constructor function with one assignment- expression as an argument; again, the function call is a full-expression. ]

1.9.14: [Note: the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument. ]

1.9.16: There is a sequence point at the completion of evaluation of each full-expression.

5-1: [Note: Clause 5 defines the syntax, order of evaluation, and meaning of expressions. An expression is a sequence of operators and operands that specifies a computation. An expression can result in a value and can cause side effects.

5-4: Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.  The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [Example:
    i = v[i++];    // the behavior is unspecified
    i = 7, i++, i++;// i becomes 9
    i = ++i + 1;    // the behavior is unspecified
    i = i + 1;    // the value of i is incremented
—end example]



[ 本帖最后由 pangding 于 2010-12-6 21:13 编辑 ]
2010-12-06 21:10
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
半吊子的路过 ,/

我就是真命天子,顺我者生,逆我者死!
2010-12-06 21:14
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
收藏
得分:0 
回复 4楼 pangding
谢谢4楼的朋友pangding对我贴中存在的问题指出来哈,我接受你的观点。之后看到这个帖子内容可以参考我们两个发表的意见哈。
2010-12-07 22:15
ml232528
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:5
帖 子:367
专家分:879
注 册:2007-7-23
收藏
得分:0 
回复 4楼 pangding
y = (4 + x++) + (6 + x++);
没看懂
你的意思是说 这条语句执行完了 编译器只对x递增一次 也符合标准???

-︻┻┳═一 ☆ 悲伤的代价就是让自己明白什么是最重要的和应该珍惜的
2010-12-12 00:02
懂也不懂
Rank: 4
等 级:业余侠客
威 望:2
帖 子:73
专家分:224
注 册:2010-12-1
收藏
得分:0 
看看,路过
2010-12-12 00:53
pangding
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:北京
等 级:贵宾
威 望:94
帖 子:6784
专家分:16751
注 册:2008-12-20
收藏
得分:0 
回复 7楼 ml232528
这个观点我先保留一下。我是这么觉得的。


我后来和一个朋友讨论了一下这个,意见还不太一样。他可能会研究研究,我最近没怎么想过这个了。
这么写法肯定是有问题的,只不过他认为这个是一个 unspecified。


[ 本帖最后由 pangding 于 2010-12-12 01:05 编辑 ]
2010-12-12 01:02
八画小子
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:37
帖 子:709
专家分:2063
注 册:2010-11-11
收藏
得分:0 
回复 9楼 pangding
我个人认为,对于这个问题只要了解有这么回事就可以了,不必太过于追究。毕竟我们是用IDE在编程,有问题可以查自己使用的IDE手册。不是很强求细节的,可以不用太上心。编程重在算法,而不是某一种语言。如果太有精力了,可以看看离散数学、组合数学、数据结构、算法、编译原理。这些都对编程很有帮助,至少比追求一个C++标准中一个很细小的问题要好得多。
2010-12-13 20:29
快速回复:关于递增操作符(++)的一些讨论
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026091 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved