有人可以解释当(而不是)作为参数传递给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()
创建临时A
,move
传递对该临时的引用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