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

如何通过移动构造函数将派生对象作为右值引用传入基类指针成员?

问题原因分析

你的段错误根源在于右值引用版本的composite构造函数保存了临时对象的指针。当你传递primitive(10)这类临时对象给该构造函数时,这些临时对象的生命周期仅持续到构造函数执行完毕。构造函数结束后,临时对象被销毁,left和right指针就变成了悬空指针,后续调用evaluate()时访问已释放的内存,触发段错误。

比如composite exp1 = composite(primitive(10), primitive(2), &add);中,primitive(10)和primitive(2)是临时对象,构造函数保存它们的地址后,这两个临时对象立刻被销毁,exp1的left和right指向无效内存。

修复方案

解决这个问题的核心是让composite管理其左右子对象的生命周期,推荐使用智能指针(比如std::unique_ptr)替代裸指针,自动处理对象的创建和销毁,避免悬空指针。

以下是修复后的完整代码:

#include <iostream>
#include <memory> // 引入智能指针头文件
using namespace std;

typedef int (*operation)(int, int);

int add(int a, int b){
    return a + b;
}

int subtract(int a, int b){
    return a - b;
}

class base_object{
public:
    virtual int evaluate() = 0;
    virtual ~base_object(){}
};

class primitive: public base_object{
private:
    int value;
public:
    primitive(int _value): value(_value){}
    // 默认移动构造足够,无需手动实现
    int evaluate() override{
       return value; 
    }
};

class composite: public base_object{
private:
    // 使用unique_ptr管理子对象所有权
    unique_ptr<base_object> left;
    unique_ptr<base_object> right;
    operation op;
public:
    explicit composite() = delete;
    
    // 接受unique_ptr的右值,转移所有权
    composite(unique_ptr<base_object>&& _left, unique_ptr<base_object>&& _right, operation _op):
        left(move(_left)), right(move(_right)), op(_op){
        cout<<"composite moving constructor was called"<<endl;
    }
    
    // 兼容原始指针版本(可选,建议优先用智能指针)
    composite(base_object* _left, base_object* _right, operation _op):
        left(_left), right(_right), op(_op){}
    
    int evaluate() override{
        return op(left->evaluate(), right->evaluate());
    }
};

int main(){//calculate expression ((10+2)-5)
    // 使用make_unique创建primitive,转移所有权给composite
    composite exp1 = composite(make_unique<primitive>(10), make_unique<primitive>(2), &add);
    composite exp2 = composite(make_unique<composite>(move(exp1)), make_unique<primitive>(5), &subtract);
    
    int result = exp2.evaluate();
    cout<<"final result of expression="<<result<<endl;
    return 0;   
}
关键修改点
  • 将base_object*替换为std::unique_ptr<base_object>:unique_ptr会自动管理对象的生命周期,当composite被销毁时,其持有的子对象也会被自动销毁,避免内存泄漏和悬空指针。
  • 构造函数接受unique_ptr<base_object>&&:通过std::move转移智能指针的所有权,确保composite拥有子对象的控制权。
  • 使用std::make_unique创建对象:安全地分配内存并创建对象,避免手动管理new和delete。

这样修改后,无论是传递临时对象还是移动已有对象,都能保证指针指向的对象始终有效,不会出现段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 20:52:49