移动过载和析构函数理论。如果我是对的,有人可以回答吗?



我试图理解c++的移动重载和析构函数调用的权利。所以我做test。我的理论是:"食物"。它返回foo_test()是由move构造函数创建的,返回(作为副本??)然后在"被摧毁。返回的"食物";From foo_test() with move=overload赋值给foo my"然后被摧毁。之后,"我的";被打印并销毁了,因为它超出了范围。我接近正确答案了吗?

<标题>Main.cpp h1> 输出
01234
move cons was called
foo destructor0
move = overload was called
foo destructor0
0123456789
foo destructor10

move操作符的存在与否对构造函数和析构函数的工作方式没有任何影响。每个对象都是通过析构函数构造的,并在某个时候被销毁。这是c++的基础。移动语义不会改变这一点。这是要理解的第一件重要的事情。

move构造函数只是另一个构造函数,也算作构造函数。move赋值操作符是完全无关的。被移出的物体在某一时刻一定会被破坏。移动到的对象是先前构造的。在某一时刻,这两个对象都将被构造和销毁。

foo foo_test() {
foo in{10};
return in;
}

但是这里你引入了另一个因素:复制省略。这里,从c++ 11开始,当从foo_test()返回in时,编译器被允许(但不是必须)完全省略副本。

通常return从函数中删除任何对象执行隐式复制(或移动)。但在这里,根据编译器的突发奇想,不会发生复制或移动。in对象有效地在调用者的上下文中构造,而return是一个什么都没有的东西。它并没有返回。任何东西。在调用者的上下文中,一旦返回,它就已经有了一个完全成熟的对象。然而,这里:

my = foo_test();

因为返回值被赋值给一个现有对象,所以在某些时候必须调用它的赋值或移动操作符。然后,在foo_test中构造的对象被销毁(不管return是否省略了它的隐式副本)。

所以,你的问题的答案是:这里发生的事情是……视情况而定。这取决于你的编译器决定做什么。

理解这里到底发生了什么并不重要。重要的是要明白:

  1. 在c++中,每个对象都被构造和销毁。
  2. 移动操作符的存在或不存在不会改变这一点。在对象被构造或销毁之后,它可能会被移到或移出,但它不会影响它的构造或销毁。
  3. 对于前两条规则,对象移动构造函数算作构造函数。
  4. c++有可选的或强制的拷贝省略,这取决于c++版本。所有的副本省略都有效地使副本消失。它仍然没有改变所有对象都被构造和销毁的规则。
  5. 所有的复制省略可能做的就是"当从函数执行return的隐式复制时,将两个对象转换为一个对象。这是前两条规则可以被扭曲的最大范围。实际上,这两个对象,在被调用方和调用方的上下文中,成为一个对象,遵循相同的规则,否则。

最新更新