何时是"replaced"不再可寻址的变量

When is a variable that is "replaced" no longer addressable

本文关键字:寻址 变量 不再 replaced 何时      更新时间:2023-10-16

如果我将新变量分配给旧变量,旧变量将不再可寻址,但我不确定它何时超出范围:

例如:

std::vector<int> foo() {
    return std::vector<int>{3,4,5};
}
int main() {
    std::vector<int> v{1,2,3};
    v = foo();  //when is the first vectors destructor called? 
                //before or after "foo()" has been called?
                //is it called?
}

而且,如果直到调用foo之后才调用它,那么在调用foo((之前如何销毁v?

v = foo();

上面的语句是一个移动赋值(复制赋值适用于C++11之前的编译器(。在任何一种情况下,调用foo()的结果都是赋值所必需的,因为它是相应赋值运算符的输入参数,所以在调用foo()之后释放v管理的资源,并且在复制/移动赋值运算符中执行内存管理。

注意,我没有提到对v析构函数的任何调用,因为那时不会调用析构函数。v管理的内存将被解除分配,同时调用各个元素的析构函数。在vector<int>的情况下,每个int的析构函数都是NOP,所以它们只是在概念上调用的。

然后,vector将分配足够的内存,以便能够保存foo返回的vector的内容(复制分配(,或者控制由foo返回的vector管理的内存(移动分配(。当然,如果现有内存足够大,可以容纳新内容,那么vector实现可以自由跳过先释放后分配。

v超出作用域时,v的析构函数将运行。在您提供的示例中,这种情况发生在main()的末尾。

foo()的返回值是在将其分配给main()中的v之前创建的。

当析构函数超出作用域时,即在main的末尾调用析构函数。

序列是调用foo((,它返回一个向量。然后调用一个复制赋值操作符,将返回的向量复制到原始向量。然后,返回的向量被销毁,因为它是一个临时变量。

v只有在超出范围时才会被销毁。

然而,foo()创建一个临时对象,然后返回该对象,然后将其分配给v。然后销毁临时文件(在将其分配给v之后(。CCD_ 24然后在CCD_。

请注意,在实践中,编译器优化了很多这方面的内容——它确实返回值优化,这样它就不会返回一个临时的,然后分配给v,而是直接在v上工作。此外,还有一个移动分配操作符,它将内存的所有权从临时交换到v,而不需要先复制它。