什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?
如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
将此主题视为以下主题的续篇:
上一部分
未定义的行为和序列点
让我们重新审视这个有趣而复杂的表达(斜体短语取自上述主题*smile*):
i += ++i;
Run Code Online (Sandbox Code Playgroud)
我们说这会调用undefined-behavior.我假定说这个的时候,我们隐含假设型的i是内置的类型之一.
如果什么类型的i是用户定义类型?比如它的类型是Index在本文后面定义的(见下文).它还会调用未定义的行为吗?
如果是,为什么?它不等同于写作i.operator+=(i.operator++());甚至语法上更简单 i.add(i.inc());吗?或者,他们是否也调用未定义的行为?
如果不是,为什么不呢?毕竟,对象在连续的序列点之间i被修改两次.请回想一下经验法则:表达式只能在连续的"序列点"之间修改一个对象的值.如果 i += ++i是表达式,那么它必须调用未定义的行为.如果是,那么它的等价物i.operator+=(i.operator++());也 i.add(i.inc());必须调用undefined-behavior似乎是不真实的!(据我所知)
或者,i += ++i不是一个开头的表达?如果是这样,那么它是什么以及表达式的定义是什么?
如果它是一个表达式,并在同一时间,其行为也是定义良好的,那么就意味着与表达相关序列点的数量在某种程度上取决于该类型的参与表达操作数.我是否正确(甚至部分)?
顺便问一下,这个表达怎么样?
//Consider two cases:
//1. If a is an array of a built-in type
//2. If a is user-defined type which overloads the …Run Code Online (Sandbox Code Playgroud) 以下代码:
myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue() << myQueue.dequeue();
Run Code Online (Sandbox Code Playgroud)
将"ba"打印到控制台
而:
myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue();
cout << myQueue.dequeue();
Run Code Online (Sandbox Code Playgroud)
打印"ab"为什么会这样?
似乎cout首先调用最外层(最接近;)函数并且正在进行中,它的行为方式是什么?
以下表达式通常用于演示未定义的未指定行为:
f() + g()
Run Code Online (Sandbox Code Playgroud)
如果f()和g()都有一些共享对象的副作用,则行为是不确定的不确定,因为执行的顺序是未知的.f()可以在之前评估,g()反之亦然.
现在我想知道当你在一个对象上链接成员函数时会发生什么.比方说,我有一个类,叫做实例的实例obj,它有两个成员函数,foo()而bar()这两个修改的对象.这些函数的执行顺序不是可交换的.在一个接一个之前调用一个的效果与用另一个方式调用它们的效果不同.这两个方法都返回一个引用,*this以便它们可以像这样链接:
obj.foo().bar()
Run Code Online (Sandbox Code Playgroud)
但这是不明确的行为吗?我在标准中找不到任何东西(不可否认只是扫描),区分了这个表达式和我在帖子顶部给出的表达.两个函数调用都是full-expression的子表达式,因此它们的执行顺序是未指定的.但肯定foo() 必须先评估,以便bar()知道要修改哪个对象.
也许我错过了一些明显的东西,但我无法看到序列点的创建位置.
在cpp中,以下代码片段的结果是:5 5 5但是在java中,相同代码片段的结果是:3 5 7我不知道为什么,是否有人可以解释它?非常感谢!
class H
{
public:
H &pr (int n, char * prompt)
{
cout<<prompt<<n<<" ";
return *this;
}
H &fn(int n)
{
return pr(n,"");
}
};
void test()
{
int v=3;
H h;
h.fn(v).fn(v=5).fn((v=7));
}
Run Code Online (Sandbox Code Playgroud) #include <iostream>
using namespace std;
int a = 8;
int g()
{
a++;
return a - 1;
}
int f()
{
a++;
return a;
}
int main()
{
cout << g() << " " << f() << " " << g() + f() << endl;
system("PAUSE");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出为"11 11 18"
我总是希望它的工作原理如下所示:"x = x ++"后的x是什么?
但是当我试图测试它时:
int x = 0;
x = x++;
printf("x = %d\n", x);
Run Code Online (Sandbox Code Playgroud)
结果不是我想象的那样但是1.我们在VS2012和g ++(版本4.7)中测试了它.
请注意,此代码按预期打印0:
int x = 0;
int y = x++;
printf("y = %d\n", y);
Run Code Online (Sandbox Code Playgroud)