作为参数传递给 std::move 时的临时对象的生存期



有人可以解释当(而不是)作为参数传递给std::move时,临时对象的生存期会受到怎样的影响。在下面的代码中,我使用带和不带std::move创建 r 值引用。令我惊讶的是,我没有得到预期的结果。

#include <iostream>
class A {
public:
A() {
std::cout << "const" << std::endl;
}
A(A&& a) {
std::cout << "move const" << std::endl;
}
~A() {
std::cout << "dest" << std::endl;
}
};
void fn(A&& a) {
std::cout << "inside fn" << std::endl;
}
int main() {
A&& a_ref = std::move(A());
fn(std::move(A()));
A&& a_ref1 = A();
std::cout << "end" << std::endl;
}

这是我得到的输出

const
dest
const
inside fn
dest
const
end
dest

当您通过函数传递临时对象的生存期时,该对象的生存期延长不起作用。 当你这样做时

A&& a_ref = std::move(A());

A()绑定到的右值引用不是a_ref而是move的参数。 该功能结束时,该参数将被销毁,这意味着它绑定的临时参数也将被销毁。这就是为什么我们看到

const
dest

在输出和a_ref中是一个悬空的围栏。

fn(std::move(A()));

A()创建临时Amove传递对该临时的引用fun。临时对象仍然绑定到move的参数,但由于临时对象至少存在到创建它们的完整表达式结束,因此当我们进入fun时,A()仍然处于活动状态。临时的只会在fun结束后销毁

,这与
const
inside fn
dest

然后用

A&& a_ref1 = A();

在这里,我们将临时直接绑定到右值引用。这会将临时的生存期延长为引用的生存期。 由于引用是 main 的本地引用,因此它仅在main结束时被"销毁",因此这就是您看到输出的原因

const
end
dest

这是几乎相同的程序,包含更多信息:

class A {
std::string s;
public:
A(std::string s1): s(std::move(s1)) {
std::cout << "ctor for: " << s << std::endl;
}
A(A&& a) {
std::cout << "move ctor for: " << a.s << std::endl;
}
~A() {
std::cout << "dtor for: " << s << std::endl;
}
};
void fn(A&& a) {
std::cout << "inside fn" << std::endl;
}
int main() {
A&& a_ref = std::move(A("1")); // life of temporary is not extended
fn(std::move(A("2")));  // temporary is still alive when calling fn
// above is essentially the same as just: fn(A("2"));
A&& a_ref1 = A("3"); // life of temporary is extended
A&& a_ref2 = std::move(A("4")); // life of temporary is not extended
std::cout << "end" << std::endl;
}

代码:https://godbolt.org/z/xT9TcWvqh

延长临时的生存期需要将临时直接分配给右值或常量左值引用。A("3")就是这种情况,但A("1")A("4")不是这种情况,它们没有直接分配给它们的参考,因此它们的参考不会延长它们的寿命。

输出和说明:

ctor for: 1
dtor for: 1    ==> the temporary is dead, life is not extended 
ctor for: 2
inside fn
dtor for: 2    ==> end of statement creating 2 (after calling fn)
ctor for: 3    ==> life of 3 is extended
ctor for: 4
dtor for: 4    ==> the temporary is dead, life is not extended 
end
dtor for: 3    ==> 3, whose life was extended is dead at the end of main

最新更新