You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用抽象类的右值引用成员?解决abort()报错问题

问题分析与解决方案

崩溃原因

你遇到的崩溃核心是悬垂引用问题,和所谓的“类型从Derived变Base”无关:

  • 临时对象Derived(1,1)在Bag bag(Derived(1,1));执行时,会被绑定到Bag构造函数的Base&& b参数,但临时对象的生命周期不会因为绑定到类的成员引用而延长——只有绑定到局部的const引用/右值引用变量时,生命周期才会同步延长。因此Bag构造完成后,这个临时Derived对象会立刻被销毁。
  • 因为Base有虚析构函数,销毁Derived对象时会按正确的多态析构顺序:先调用Derived的析构函数(释放自身的_arr),再调用Base的析构函数(释放Base的_arr),整个对象的内存被完全回收。此时Bag类中的_b就是指向已释放内存的悬垂引用,调用_b.func()时,程序试图通过虚函数表访问已销毁的对象,直接触发abort报错。
  • 删掉Base的虚析构后“能运行”是未定义行为的侥幸结果:没有虚析构时,编译器会按静态类型(Base)调用析构函数,Derived的析构不会被执行,对象内存可能未被完全回收,虚函数表地址碰巧还在原位置,才让func调用“看起来正常”,但这完全不可靠,随时可能崩溃。

保留虚析构的修改方案

不能用引用成员来持有多态临时对象,应该用智能指针管理对象的生命周期,推荐使用std::unique_ptr(独占所有权,轻量高效):

修改后的完整代码

#include <iostream>
#include <memory>
using namespace std;

class Base
{
public:
    Base(int n) :_n(n) { _arr = new int[n]; }
    virtual ~Base() { delete[] _arr; }
    Base(Base&& other) { _n = other._n; _arr = other._arr; other._arr = nullptr; other._n = 0; }
    virtual void func() = 0;

private:
    int _n;
    int* _arr;
};

class Derived : public Base
{
public:
    Derived(int m, int n) : Base(n), _m(m) { _arr = new int[m]; }
    ~Derived() { delete[] _arr; }
    Derived(Derived&& other) : Base(std::move(other)) { _m = other._m; _arr = other._arr; other._arr = nullptr; other._m = 0; }
    void func() override { cout << "func"; }
private:
    int _m;
    int* _arr;
};

class Bag
{
public:
    // 接收unique_ptr并转移所有权
    Bag(std::unique_ptr<Base> b) : _b(std::move(b)) {}
    void func() { _b->func(); }
private:
    std::unique_ptr<Base> _b; // 用智能指针持有多态对象
};

int main()
{
    // 创建Derived对象并转移所有权给Bag
    Bag bag(std::make_unique<Derived>(1, 1));
    bag.func();
}

关键说明

  • std::unique_ptr<Base>可以正确管理多态对象的生命周期,当Bag被销毁时,会自动调用Base的虚析构函数,进而触发Derived的析构函数,保证内存正确释放。
  • 用std::make_unique创建对象是更安全的写法(避免内存泄漏风险),也可以用std::unique_ptr<Base>(new Derived(1,1))替代。

内容的提问来源于stack exchange,提问作者Ryime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 02:31:32