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

C++中重载&&运算符失败及运行时访问冲突求助

开闭原则实现中的编译与运行时问题分析与解决

问题背景

我在学习设计原则课程,尝试实现开闭原则:定义不同Specification(规格)类,交由Filter(过滤器)类校验实体是否合法。

现有代码结构

基类定义

template <typename T>
struct Specification {
    virtual ~Specification() {}
    virtual bool is_satisfied(T* item) = 0;
};


template <typename T>
struct Filter {
    virtual std::vector<T*> filter(std::vector<T*> items, Specification<T>& spec) = 0;
    
};

继承类定义

template <typename T>
struct AndSpecification : Specification<T> {
    Specification<T>& first;
    Specification<T>& second;
    AndSpecification(Specification<T>&& first, Specification<T>&& second) : first(first), second(second) {}
    
    bool is_satisfied(T* item) override {
        return first.is_satisfied(item) && second.is_satisfied(item);
    }

};


struct BetterFilter : Filter<Product> {
    std::vector<Product* > filter(std::vector<Product*> items, Specification<Product>& spec);
};

struct ColorSpecification : Specification<Product> {
    Color color;
    ColorSpecification(Color color) :color(color) {}
    bool is_satisfied(Product* item);
};

struct SizeSpecification : Specification<Product> {
    Size size;
    SizeSpecification(Size size) :size(size) {}
    bool is_satisfied(Product* item);
};

重载运算符尝试

我尝试在全局作用域重载&&运算符:

template <typename T>
AndSpecification<T> operator&&(Specification<T>&& one, Specification<T>&& two) {
    return AndSpecification<T>{one, two};
}

遇到的问题

  1. 编译错误
    编译时出现如下错误:

    Error   C2440   '<function-style-cast>': cannot convert from 'initializer list' to 'AndSpecification<Product>'  DesignPrinciples    C:\Users\ania\source\repos\DesignPrinciples\Main.cpp    24  
    

    改为非模板版本仍无法编译。

  2. 运行时崩溃
    添加std::move后可编译,但运行时出现读取访问冲突,触发位置为:

    AndSpecification<Product> spec = ColorSpecification(Color::green) && SizeSpecification(Size::large);
    

问题原因分析

编译错误原因

AndSpecification的构造函数接收右值引用参数,但初始化列表中却将其绑定到左值引用成员first和second。当用AndSpecification<T>{one, two}初始化时,one和two是函数参数(属于左值,尽管类型是右值引用),编译器无法完成这种类型转换,导致初始化失败。

运行时崩溃原因

即使添加std::move编译通过,ColorSpecification(Color::green)和SizeSpecification(Size::large)是临时对象,生命周期仅到表达式结束就会销毁。而AndSpecification的成员是引用,会指向这些已销毁的临时对象,后续调用is_satisfied时会访问已释放的内存,触发读取访问冲突。

解决方法

核心问题是引用绑定到临时对象导致的悬空引用,需要改为存储对象而非引用,或用智能指针管理生命周期,以下是两种可行方案:

方案1:使用智能指针管理多态对象

修改AndSpecification的成员为智能指针,转移临时对象的所有权,避免悬空引用:

#include <memory>

template <typename T>
struct AndSpecification : Specification<T> {
    std::unique_ptr<Specification<T>> first;
    std::unique_ptr<Specification<T>> second;

    AndSpecification(std::unique_ptr<Specification<T>>&& f, std::unique_ptr<Specification<T>>&& s)
        : first(std::move(f)), second(std::move(s)) {}

    bool is_satisfied(T* item) override {
        return first->is_satisfied(item) && second->is_satisfied(item);
    }
};

调整运算符重载,适配智能指针的转移:

template <typename T>
AndSpecification<T> operator&&(std::unique_ptr<Specification<T>>&& one, std::unique_ptr<Specification<T>>&& two) {
    return AndSpecification<T>{std::move(one), std::move(two)};
}

使用方式:

auto spec = std::make_unique<ColorSpecification>(Color::green) && std::make_unique<SizeSpecification>(Size::large);

方案2:存储值类型(适用于可安全拷贝的场景)

如果Specification子类支持移动/拷贝且无多态切片风险,可直接存储值:

template <typename T>
struct AndSpecification : Specification<T> {
    Specification<T> first;
    Specification<T> second;

    AndSpecification(Specification<T>&& f, Specification<T>&& s)
        : first(std::move(f)), second(std::move(s)) {}

    bool is_satisfied(T* item) override {
        return first.is_satisfied(item) && second.is_satisfied(item);
    }
};

调整运算符重载:

template <typename T>
AndSpecification<T> operator&&(Specification<T>&& one, Specification<T>&& two) {
    return AndSpecification<T>{std::move(one), std::move(two)};
}

使用方式保持原有形式即可,临时对象会被移动到AndSpecification中:

AndSpecification<Product> spec = ColorSpecification(Color::green) && SizeSpecification(Size::large);

额外优化建议

  • 将Filter::filter的参数改为const Specification<T>&,因为校验操作不应该修改规格对象。
  • 如果使用方案2,确保Specification子类实现了正确的移动构造函数,避免切片问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:05:43