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

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

本文关键字:应用 复制 为什么 构造函数 结果 指针 引用 显示 共享      更新时间:2023-10-16

这段代码的输出是

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"。

代码实际是这样做的:

cout.operator<<( a.get() ).operator<<( b.get() );

operator<<( operator<<( cout, a.get() ), b.get() );

(由于重载问题,我无法使后者编译,但它确实在幕后发生)

这意味着代码在b.get()之前计算std::endl,在a.get()之前计算b.get()。因此b.g get()将val的指向值增加1然后返回1,a.g get()将val的指向值增加1然后返回2。运算符在求值参数后按预期顺序调用。我猜这是编译器依赖的,但我运行了你的代码并得到了21。

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

所以b现在拥有自己的指针,它和a的指针保存着相同的值,也就是指向相同的地址。由于您在get()上增加了值,因此返回的值永远不会相同,因此您永远不会得到22作为结果。

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

首先为对象b调用get函数,然后为对象a调用get函数,因此得到一个0/p = 21

(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
从上面的调试会话中,我们可以看到流程和行为。

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