共享解除引用的指针值显示不同的结果(应用隐式复制构造函数时)。为什么?

时间:2015-06-08 11:10:40

标签: c++ pointers copy-constructor

这段代码的输出是

21

我无法向自己解释。我的想法(我学到的)是调用隐式复制构造函数(由赋值触发)并且所有元素都是逐位复制的。但是,这不适用于外部元素,例如私有变量val,它是一个指针。因此b有一个不同的指针,但是它指向同一个元素。

所以我希望结果是

22

.get()a调用b两次,因此解除引用的指针值应为1(在第一个get()之后),然后2(在第二个get()之后)。最后,这些值将写入控制台输出。

C ++代码:

#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;
}

4 个答案:

答案 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,这是我的习惯。