woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

c 函数参数求值顺序

学过 c 的人都知道,c 中函数参数的求值顺序是由编译器的实现决定的,c 标准并没有规定求值顺序。每当讲到这,下面这个经典的例子总会出现:

int i = 0;
printf("%d,%d", i++, i++);

我们没办法确定是打印1,0,还是打印0,1,这取决于哪个i++先执行。

我很少碰到参数求值顺序的问题,我以为我不会碰到,也就慢慢的忘记了这条警告,今天我以一种让我恐惧的方式碰到了。

send(sfd, mPacket.content(), mPacket.contentSize(), MSG_NOSIGNAL));

通常情况,mPacket.content() 是一个 const 函数,它不会改变mPacket的内容。后来,功能升级,mPacket.content() 改成了非 const 函数,祸根由此种下。升级后的mPacketmPacket.contentSize() 在有限的情况下,依赖于 mPacket.content() 的调用。在 send 函数调用时,因为函数参数求值顺序不确定,所以 mPacket.content() mPacket.contentSize() 的调用顺序也就不确定,如果先调用前者,一切正常,如果先调用后者,等前者调用时,mPacket.contentSize() 的值已经不是它传递给 send 函数的那个值了。虽然在这里参数有求值顺序依赖,但程序行为没有影响,但是,我不可能永远这么幸运。

我之所以感到恐惧,是因为我之前没有意识到,类方法本质上和 i++ 一样具有副作用,用在函数参数中时,要小心,而在我意识到之前,我写的代码是没有保障的(虽然它现在没出问题)。

诫言:不要在同一个函数调用中使用i++两次,不要在同一个函数调用中使用同一个类的两个方法,除非他们是const的,并且没有操作mutable的成员变量。标准库的 std::string::c_str() string::size() 满足这两个条件。与其靠小心(使两个成员函数结果不依赖于调用顺序),不如靠接口(把它们声明为const)。首先使用的人会放心的同一个函数调用中使用,而不担心求值顺序(就像std::string,实现的人也省心,如果违反接口,编译器也会警告。



posted on 2010-12-29 14:12 肥仔 阅读(803) 评论(0)  编辑 收藏 引用 所属分类: C++ 基础


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理