这段代码的输出是
21
我无法向自己解释。我的想法(我学到的)是调用隐式复制构造函数(由赋值触发)并且所有元素都是逐位复制的。但是,这不适用于外部元素,例如私有变量val
,它是一个指针。因此b
有一个不同的指针,但是它指向同一个元素。
所以我希望结果是
22
由.get()
和a
调用b
两次,因此解除引用的指针值应为1
(在第一个get()
之后),然后2
(在第二个get()
之后)。最后,这些值将写入控制台输出。
#include <iostream>
using namespace std;
class A {
int *val;
public:
A() {
val = new int;
*val = 0;
}
int get() {
return ++(*val);
}
};
int main() {
A a, b = a;
cout << a.get() << b.get();
return 0;
}
答案 0 :(得分:2)
使用cout时,a.get()
和b.get()
的评估没有按特定顺序进行。因此,在您的示例中,首先评估b.get()
(至1),然后评估a.get()
(至2),然后在屏幕上显示“21”。
答案 1 :(得分:1)
您的问题是序列点之一:std::cout << a.get() << b.get();
没有严格定义a.get()
和b.get()
的评估顺序。
有关所有解释,请参阅this answer here。
答案 2 :(得分:1)
首先为对象b调用get函数,然后调用对象a,因此给出o / p为2 1
(gdb) s
main () at so2.c++:20
20 cout << a.get() << b.get();
(gdb) p &a
$6 = (A *) **0x7fffffffd0f0**
(gdb) p &b
$7 = (A *) *0x7fffffffd0e0*
(gdb) s
A::get (this=*0x7fffffffd0e0*) at so2.c++:14
14 return ++(*val);
(gdb) p *val
$8 = 0
(gdb) n
15 }
(gdb) p *val
$9 = 1
(gdb) s
A::get (**this=0x7fffffffd0f0**) at so2.c++:14
14 return ++(*val);
(gdb) s
15 }
(gdb) p *val
$10 = 2
从上面的调试会话中我们可以看到流程和行为。
答案 3 :(得分:1)
这就是代码实际执行的操作:
cout.operator<<( a.get() ).operator<<( b.get() );
或
operator<<( operator<<( cout, a.get() ), b.get() );
(由于重载问题,我不能让后者编译,但它确实在幕后发生)
这意味着代码在b.get()之前计算std :: endl,在a.get()之前计算b.get()。因此,b.get()将val的指向值增加1,然后返回1,a.get()将val的指向值增加1并返回2.在计算参数后,将按预期顺序调用运算符。我猜这是依赖于编译器的,但我运行了你的代码并得到了21。
在这种情况下,您使用的是隐式复制构造函数。它的作用是将实例a的内存复制到实例b。 (正如你所说,逐字节)
所以b现在拥有自己的指针,该指针保存与指针相同的值,即指向同一地址。由于你增加了get()的值,返回的值永远不会相同,所以你永远不会得到22。
编辑:你实际上并没有使用std :: endl,这是我的习惯。