销毁派生类后使用基类的成员 [英] Using members of base class after destruction of derived class

查看:90
本文介绍了销毁派生类后使用基类的成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose that we have a simple struct:

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

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

From implementation point, the destructor RefCounters::~RefCounters should do nothing, since all its members have primitive type. This means that if an object of this type is destroyed with explicit call of destructor (but its memory is not deallocated), then we would be able to work with its members normally after the object is dead.

现在假设我们还有其他一些从RefCounters派生的类.假设RefCountersDerived类的基类中仅存在一次.假设为类Derived的对象显式调用了析构函数,但其​​内存释放.之后可以访问成员strong_cntweak_cnt吗?

Now suppose that we have some more classes derived from RefCounters. Suppose that RefCounters is present exactly once among base classes of Derived class. Suppose that destructor is called explicitly for an object of class Derived, but its memory is not deallocated. Is it OK to access members strong_cnt and weak_cnt after that?

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

From implementation point, it should be OK, at least when there is no virtual inheritance involved. Because Derived* can be statically cast to RefCounters* (adding compile-time constant offset to address), and the memory of RefCounters should not be touched by destructor of Derived class.

这是一个代码示例:

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 ++标准视为未定义的行为?有什么实际原因使其无法工作?可以通过较小的更改或添加一些约束使其合法吗?

Is such code considered undefined behavior by C++ standard? Is there any practical reason why it can fail to work? Can it be made legal by minor changes or adding some constraints?

P.S.据推测,这样的代码示例允许将intrusive_ptr + weak_ptr组合在一起,这样,如果至少有一个weak_ptr仍然指向它,则总是可以从一个对象指针中获取weak_ptr. 此问题中的详细信息... >

P.S. Supposedly, such code sample allows to make intrusive_ptr + weak_ptr combo, such that weak_ptr can be always obtained from an object pointer if at least one weak_ptr is still pointing at it. More details in this question.

推荐答案

我认为您的方法不好.注释中有一个不错的链接,该链接显示了有关标准细节的辩论.一旦争论不休,很有可能不同的编译器将以不同的方式实现此细节.更.同一编译器可能会将其实现方式从一个版本更改为另一个版本.

I believe that your approach is bad. There is a nice link in comments that shows debate about the details of the standard. Once there is a debate there is good chance that different compilers will implement this detail differently. Even more. The same compiler may change its implementation from one version to another.

您越用不同的暗角,遇到问题的机会就越大.

The more you use various dark corners, the bigger is the chance that you will meet with problems.

底线.愿意实现什么?为什么不能使用普通的C ++语言功能来做到这一点?

Bottom line. What are willing to achieve? Why can't you do this using ordinary C++ language features?

这篇关于销毁派生类后使用基类的成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆