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

Shared dereferenced pointer value displays different results (when applying implicit copy constructor). Why?

这段代码的输出是

21

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

所以我预计结果是

22

.get()ab 调用两次,因此取消引用的指针值应该是 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;
}

使用 cout 时,a.get()b.get() 的计算没有特定的顺序。因此,在您的示例中,首先评估 b.get()(到 1),然后评估 a.get()(到 2),然后在屏幕上打印“21”。

您的问题是序列点之一:std::cout << a.get() << b.get(); 没有严格定义 a.get()b.get() 的求值顺序。

有关所有解释,请参阅 this answer here

首先为对象 b 调用 get 函数,然后为对象 a 调用,因此 o/p 为 2 1

(gdb) s
main () at so2.c++:20
20          cout << a.get() << b.get();
(gdb) p &a
 = (A *) **0x7fffffffd0f0**
(gdb) p &b
 = (A *) *0x7fffffffd0e0*
(gdb) s
A::get (this=*0x7fffffffd0e0*) at so2.c++:14
14              return ++(*val);
(gdb) p *val
 = 0
(gdb) n
15          }
(gdb) p *val
 = 1
(gdb) s
A::get (**this=0x7fffffffd0f0**) at so2.c++:14
14              return ++(*val);
(gdb) s
15          }
(gdb) p *val
 = 2

从上面的调试会话中我们可以看到流程和行为。

这就是代码的实际作用:

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,然后 returns 1,并且 a.get() 将 val 的指向值增加 1 和 returns 2。运算符被调用评估参数后的预期顺序。我猜这取决于编译器,但我 运行 你的代码也得到了 21。

在这种情况下,您使用的是隐式复制构造函数。它所做的是将你的实例a的内存复制到实例b。 (如你所说,逐字节)

所以 b 现在拥有自己的指针,该指针与 a 的指针具有相同的值,即指向相同的地址。由于您增加了 get() 的值,返回的值永远不会相同,因此您永远不会得到 22。

编辑:你实际上没有使用std::endl,这是我的习惯。