对移动构造函数的误解
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
的单独调用的参数没有重叠的存储生命周期。因此,他们可以使用相同的存储空间。
我有这样的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
的单独调用的参数没有重叠的存储生命周期。因此,他们可以使用相同的存储空间。