如果我在堆栈上声明了一个对象,并且我返回了对它的引用,我相信我将无法再访问它,因为它超出了范围。正确的?
如果我只返回对象本身(不是对它的引用)怎么办?会调用复制构造函数吗?(我听说过“移动构造函数”这个词,但从我读到的,这似乎是一个新功能。有人可以详细说明一下吗?)
在什么情况下会调用析构函数?
如果我在堆栈上声明了一个对象,并且我返回了对它的引用,我相信我将无法再访问它,因为它超出了范围。正确的?
如果我只返回对象本身(不是对它的引用)怎么办?会调用复制构造函数吗?(我听说过“移动构造函数”这个词,但从我读到的,这似乎是一个新功能。有人可以详细说明一下吗?)
在什么情况下会调用析构函数?
如果我在堆栈上声明了一个对象,并且我返回了对它的引用,我相信我将无法再访问它,因为它超出了范围。正确的?
正确,析构函数超出范围时将被调用。
如果我只返回对象本身(不是对它的引用)怎么办?会调用复制构造函数吗?
可以调用复制构造函数和析构函数,但通常编译器将执行返回值优化,并且不会进行复制、析构函数或移动。
要了解移动构造函数,请阅读移动语义和右值引用。
如果我在堆栈上声明了一个对象,并且我返回了对它的引用,我相信我将无法再访问它,因为它超出了范围。正确的?
正确,许多编译器也会给你警告。
如果我只返回对象本身(不是对它的引用)怎么办?会调用复制构造函数吗?
它会调用复制构造函数。标准中的 std::array 没有定义 std::move 构造函数,因为它在内部使用堆栈内存。因此将调用复制构造函数。
在什么情况下会调用析构函数?
在这两种情况下,都会调用析构函数。只是在移动构造函数之后,我们将所有指针/句柄移动到其他对象,因此对象状态将是一种空的(但一致)。
编译器将尝试优化此类函数以消除复制操作。生成的代码将表现得好像对象是在函数以适当的生命周期返回它的点创建的。参考这里。这取决于编译器,以及代码本身在构造和使用点的结构。也可能无法进行优化,在这种情况下,您可能会调用复制或移动构造函数(如果可用)。
如果编译器优化了函数,那么当使用点的对象超出最近的块范围时,将调用析构函数。
如果没有优化,那么对象会在使用点被复制到另一个对象(一次调用复制/移动构造函数),然后函数中的对象将被销毁(如果被复制),最后是被复制/的析构函数移动的对象将在函数返回它的位置(使用点)离开最近的块范围时被调用。
但是,如果您从函数返回一个临时值,那么您将返回一个指向已破坏内存的引用或指针,因为您的临时值将在函数返回时超出范围并被销毁。