繁体   English   中英

在破坏派生类之后使用基类成员

[英]Using members of base class after destruction of derived class

假设我们有一个简单的结构:

struct RefCounters {
    size_t strong_cnt;
    size_t weak_cnt;
    RefCounters() : strong_cnt(0), weak_cnt(0) {}
};

从实现的角度来看,析构函数RefCounters::~RefCounters应该什么都不做,因为它的所有成员都有原始类型。 这意味着如果通过显式调用析构函数来销毁此类型的对象(但其内存未被释放),那么我们将能够在对象死亡后正常使用其成员。

现在假设我们有更多来自RefCounters类。 假设RefCountersDerived类的基类中只出现一次。 假设为Derived类的对象显式调用析构函数,但释放其内存。 之后可以访问成员strong_cntweak_cnt吗?

从实现的角度来看,它应该没问题,至少在没有涉及虚拟继承时。 因为Derived*可以静态地转换为RefCounters* (将编译时常量偏移量添加到地址),并且Derived类的析构函数不应该触及RefCounters的内存。

这是一个代码示例:

struct RefCounted : public RefCounters {
    virtual ~RefCounted() {}
};

struct Base : public RefCounted {
    int val1;
    virtual void print();
};

struct Derived : public Base {
    std::string val2;
    virtual void print();
};

Derived *pDer = new Derived();
pDer->~Derived();          //destroy object
pDer->strong_cnt++;        //modify its member
std::cout << pDer->strong_cnt << pDer->weak_cnt << "\n";

这些代码是否被C ++标准视为未定义的行为? 是否有任何实际原因导致无法正常工作? 可以通过微小的变化或添加一些约束来使其合法吗?

PS据说,这样的代码示例允许使用intrusive_ptr + weak_ptr组合,这样如果至少有一个weak_ptr仍然指向它,则总是可以从对象指针获得weak_ptr。 这个问题的更多细节。

我相信你的方法很糟糕。 评论中有一个很好的链接,显示有关标准细节的争论。 一旦有争议,不同的编译器很有可能以不同的方式实现这个细节。 更。 相同的编译器可以将其实现从一个版本更改为另一个版本。

你使用各种黑暗角落越多,遇到问题的可能性就越大。

底线。 有什么愿意实现的? 为什么不能使用普通的C ++语言功能呢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM