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

在C++中实现类似类型类的信号过滤器时遭遇段错误

问题分析与修复

你的代码触发段错误的核心原因是悬空指针:
当执行filter1 * filter1 * filter1时,运算顺序是(filter1 * filter1) * filter1。第一个filter1 * filter1会生成一个临时的ProductFilter对象,这个临时对象仅在当前表达式的生命周期内存在。但后续创建的第二个ProductFilter会保存指向该临时对象的指针,当临时对象销毁后,指针变为悬空状态,调用filtered_value时访问非法内存,触发段错误。

此外,operator*的参数是ISignalFilter<T>& other(非const左值引用),临时对象无法合法绑定到这种引用,编译器的隐式转换虽然可能让代码编译通过,但会加剧生命周期问题。


修复方案

改用std::shared_ptr管理多态过滤器对象的生命周期,同时调整运算符参数以支持临时对象:

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

template <typename T>
class ISignalFilter;

template <typename F>
class ProductFilter;

template <typename T>
class ISignalFilter : public std::enable_shared_from_this<ISignalFilter<T>> {
public:
    virtual ~ISignalFilter() = default; // 基类必须有虚析构函数

    virtual T filtered_value(const T& value) const { // 改为const成员函数
        (void)value;
        std::cout << "Base case usage of method not allowed";
        std::abort();
    };

    // 修改为返回shared_ptr,参数改为const引用
    virtual std::shared_ptr<ISignalFilter<T>> operator*(const ISignalFilter<T>& other) const {
        return std::make_shared<ProductFilter<T>>(this->shared_from_this(), other.shared_from_this());
    }
};

template <typename F>
class ProductFilter : public ISignalFilter<F> {
public:
    // 接收shared_ptr并存储
    ProductFilter(std::shared_ptr<ISignalFilter<F>> a, std::shared_ptr<ISignalFilter<F>> b)
        : a_(std::move(a)), b_(std::move(b)) {}

    F filtered_value(const F& value) const override {
        return b_->filtered_value(a_->filtered_value(value));
    }

private:
    std::shared_ptr<ISignalFilter<F>> a_;
    std::shared_ptr<ISignalFilter<F>> b_;
};

template <typename T>
class IdentityFilter : public ISignalFilter<T> {
public:
    IdentityFilter() {}
    T filtered_value(const T& value) const override { return value; }
};

int main() {
    std::cout << "hello world" << std::endl;
    auto filter1 = std::make_shared<IdentityFilter<double>>();
    auto filter2 = *filter1 * *filter1 * *filter1;
    while (true) {
        double value;
        std::cout << "input:";
        std::cin >> value;
        std::cout << "filtered: " << filter1->filtered_value(value) << std::endl;
        std::cout << "filtered: " << filter2->filtered_value(value) << std::endl;
        std::cout << "The two values above should be always equal."
                  << std::endl;
    }
}

关键修改点
  1. 添加虚析构函数:基类ISignalFilter增加虚析构函数,确保通过智能指针销毁派生类对象时能正确调用析构函数。
  2. 使用std::shared_ptr管理生命周期:所有过滤器对象通过shared_ptr持有,避免悬空指针,确保对象在被引用时不会被销毁。
  3. 调整operator*:
    • 参数改为const ISignalFilter<T>& other,允许临时对象绑定;
    • 返回值改为shared_ptr<ISignalFilter<T>>,确保返回的过滤器对象生命周期由智能指针管理。
  4. enable_shared_from_this:让基类继承enable_shared_from_this,方便从当前对象获取对应的shared_ptr,避免手动创建shared_ptr导致的重复析构问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:05:23