破坏派生类

时间:2016-12-25 06:21:55

标签: c++ language-lawyer destructor

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

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

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

现在假设我们还有一些派生自RefCounters的类。假设RefCountersDerived类的基类中只出现一次Derived。假设为类strong_cnt的对象显式调用析构函数,但其​​内存解除分配。在那之后访问成员weak_cntDerived*是否可以?

从实现的角度来看,它应该没问题,至少在没有涉及虚拟继承时。因为RefCounters*可以静态转换为RefCounters(向地址添加编译时常量偏移量),Derived类的析构函数不应触及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"; 的内存。

以下是代码示例:

SELECT DATEDIFF(last_day, first_day) + 1 AS days, name, score,
    first_day, last_day
FROM (
    SELECT 
      max(date_score) as last_day, 
      min(date_score) as first_day, 
      score, 
      name 
    FROM members
    GROUP by score
  ) AS score

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

P.S。据推测,这样的代码示例允许使用intrusive_ptr + weak_ptr组合,这样如果至少有一个weak_ptr仍然指向它,则总是可以从对象指针获得weak_ptr。 this question中的更多详细信息。

1 个答案:

答案 0 :(得分:0)

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

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

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