我有一个抽象基类和一些具体的子类:
class AbstractBaseClass {
private:
bool destructed {};
public:
virtual ~AbstractBaseClass() { destructed = true; }
// returns false unless we're calling on already destructed value
bool leaked() { return destructed; };
};
class ConcreteSubClassA : public AbstractBaseClass {
public:
~ConcreteSubClassA() override {}
};
class ConcreteSubClassB : public AbstractBaseClass {
public:
~ConcreteSubClassB() override {}
};
有人可以向我解释为什么rvalue引用了子类实例 在这些情况下不会泄漏:
static_cast<AbstractBaseClass&&>(ConcreteSubClassA()).leaked(); // false
std::forward<AbstractBaseClass>(ConcreteSubClassA()).leaked(); // false
((rand() & 1)
? static_cast<AbstractBaseClass&&>(ConcreteSubClassA())
: static_cast<AbstractBaseClass&&>(ConcreteSubClassB())
).leaked(); // false
((rand() & 1)
? std::forward<AbstractBaseClass>(ConcreteSubClassA())
: std::forward<AbstractBaseClass>(ConcreteSubClassB())
).leaked(); // false
AbstractBaseClass&& abc = ConcreteSubClassA();
abc.leaked(); // false
AbstractBaseClass&& abc = static_cast<AbstractBaseClass&&>(ConcreteSubClassA());
abc.leaked(); // false
但这些呢?
AbstractBaseClass&& abc = std::forward<AbstractBaseClass>(ConcreteSubClassA());
abc.leaked(); // true
AbstractBaseClass&& abc = (rand() & 1)
? static_cast<AbstractBaseClass&&>(ConcreteSubClassA())
: static_cast<AbstractBaseClass&&>(ConcreteSubClassB());
abc.leaked(); // true
AbstractBaseClass&& abc = (rand() & 1)
? std::forward<AbstractBaseClass>(ConcreteSubClassA())
: std::forward<AbstractBaseClass>(ConcreteSubClassB());
abc.leaked(); // true
那就是为什么这么早地调用析构函数?
答案 0 :(得分:3)
临时表在完整表达式结束时被销毁(除非绑定到引用时)。这个事实解释了犯罪工作的直接用途。
将临时对象直接绑定到引用(即const&
或&&
)时,其生命周期会延长以匹配生命周期参考资料。这就是您的示例直接(或通过强制转换)绑定到右值工作的原因。
当将左值绑定到参考生命周期时,不得到扩展 - 编译器不能期望透视该构造。 不确实将左值转换为右值引用。请注意,右值引用是左值。
当然,返回leaked()
时true
的结果取决于未定义的行为:在对象被销毁时,您无法调用它而不会调用未定义的行为。