我有一个抽象的基类和一些具体的子类:
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 {}
};
有人可以向我解释为什么右值引用子类实例
在这些情况下不会泄漏:
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
也就是说,为什么析构函数这么早被调用?
最佳答案
临时变量在完整表达式的末尾销毁(除非绑定(bind)到引用)。这个事实解释了临时工作的直接用途。
将临时对象直接绑定(bind)到引用(即const&
或&&
)时,其生存期将延长以匹配引用的生存期。这就是您的示例直接(或通过强制转换)绑定(bind)到右值工作的原因。
当将左值绑定(bind)到引用生存时间时,而不是不会得到扩展-不能期望编译器看到该构造。它将左值强制转换为右值引用,并没有有所不同。请注意,右值引用是左值。
当然,返回leaked()
时true
的结果取决于未定义的行为:在销毁对象时,如果不调用未定义的行为就无法触摸它。
关于c++ - 为什么将右值引用存储在变量中会导致其悬空,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40060524/