对移动构造函数的误解

Misunderstanding with move constructor

我有这样的class,我在其中创建了一个move constructor

class Test
{
private:
    int m_a;

public:
    Test(int val) { m_a = val; }

    Test (const Test &) {}
    
    // move constructor
    Test (Test && d)
    {
        std::cout << &m_a << std::endl;   // Line X
        std::cout << &d.m_a << std::endl;
    }

    void print()
    {
        std::cout << m_a << std::endl;
    }
};

我也创建了一个函数来测试move constructor

void fun(Test a)
{ return ; }

比起在 main 函数中,我在上面创建了 class 的 2 个对象并调用函数来测试 move constructor

int main()
{
    Test a {50};
    Test b {100};

    fun(a);
    fun(std::move(a));

    fun(b);
    fun(std::move(b));

    return 0;
}

当我查看输出时,我感到很惊讶,因为 line X 中的 o m_a 变量的地址对于两个对象具有相同的地址。

0x7ffc40d37bb4   // look at this
0x7ffc40d37bac
0x7ffc40d37bb4   // look at this
0x7ffc40d37bb0

这怎么可能?它不是静态成员,这是怎么回事?编译器优化还是什么?

每次调用 fun(Test a) 时,都会在堆栈上创建一个 Test 的实例。每次fun() returns,堆栈帧被释放。

因此,当连续调用两次时,您很有可能会在堆栈上完全相同的位置创建 Test 的实例。

如果你想引用 Test,它应该是 void fun(Test&& a)

How is it possible ?

fun 的单独调用的参数没有重叠的存储生命周期。因此,他们可以使用相同的存储空间。