代码之家  ›  专栏  ›  技术社区  ›  user8510613

访问模式应用于共享指针还是原始指针?

  •  1
  • user8510613  · 技术社区  · 6 年前

    我正在研究一个小的编译器。现在我有了一个层次结构系统来表示抽象语法树(ast)。

    class Ast{
    public:
        // ...
    }
    
    class Expr : public Ast{
    public:
        // ...
    }
    
    using ExprNode = shared_ptr<Expr>;
    
    class BinaryOp : public Expr{
    public:
        ExprNode lhs;
        ExprNode rhs;
    }
    

    所有的班级 Ast 层次结构系统使用共享指针来管理其成员(如果需要),例如 BinaryOp 保留两个成员来表示其操作数。

    我想在树上应用访问者模式来生成AST的IR代码。我的问题是,如果访问者接受原始指针作为参数,或者接受共享指针作为参数,这可能会导入 shared_from_this (考虑利弊)?如果需要共享资源,我应该使用按值传递还是按引用传递?


    原始指针

    class AstVisitor{
    public:
       virtual Ast* visit(Ast* ast);
       virtual Ast* visitBinaryOp(BinaryOp* binary){
          visit(binary->lhs.get());
          visit(binary->rhs.get());
          // ...
       }
    }
    
    class Ast{
    public:
        virtual Ast* accept(AstVisitor& visitor);
    }
    
    class BinaryOp:{
    public:
        virtual Ast* accept(AstVisitor& visitor) override{
            return visitor.visitBinaryOp(this);
        }
    }
    

    SelddPPTR

    using AstNode = shared_ptr<Ast>;
    using BinaryOpNode = shared_ptr<BinaryOp>;
    class AstVisitor{
    public:
       virtual AstNode visit(AstNode ast);
       virtual AstNode visitBinaryOp(BinaryOpNode binary){
          visit(binary->lhs);
          visit(binary->rhs);
          // ...
       }
    }
    
    class Ast : public enable_shared_from_this<Ast>{
    public:
        virtual AstNode accept(AstVisitor& visitor);
    }
    
    class BinaryOp:{
    public:
        virtual AstNode accept(AstVisitor& visitor) override{
            return visitor.visitBinaryOp(static_pointer_cast<BinaryOp>(shared_from_this()));
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   Hiroki    6 年前

    我认为 C++ Core Guidelines 由b.stroustrup和h.sutter编辑将有助于解决这个问题。 请注意 this guideline :

    R.30:以智能指针作为参数,只显式表示生存期语义

    原因 如果函数只需要小部件本身,那么接受小部件的智能指针是错误的。它应该能够接受任何小部件对象,而不仅仅是那些生命周期由特定类型的智能指针管理的对象。不操作生存期的函数应改为使用原始指针或引用。

    例如,在 BinaryOp 类,管理子节点 shared_ptr 是一个很好的实践。 每个节点都有它的父节点作为所有者, SelddPPTR 用raii语义保持子树的活动。( std::unique_ptr 更可取的是,因为每个节点都有一个单独的父节点,它是一个单独的所有者。)

    奥思,自从你 visit visitBinaryOp 似乎只是需要 Ast 二进制程序 他们各自, 在这种情况下,最好接受原始指针(或引用,如果可能的话) .

        2
  •  0
  •   Maxim Egorushkin    6 年前

    接受一个函数 shared_ptr 告诉读者它复制了它,并在函数返回后保留它。

    函数不应采用 SelddPPTR 除非他们复印一份。