将右值引用绑定到左值引用 class 成员

Bind rvalue ref to lvalue ref class member

我有以下定义

class Expression {
public:
  virtual int evaluate() const = 0;
  virtual std::string to_string() const = 0;
};

class Constant : public Expression {
  int value;

public:
  Constant() = delete;
  Constant(int value) : value(value) {}
  Constant(Constant&& c) = default;

  virtual int evaluate() const { return value; }
  virtual std::string to_string() const { return std::to_string(value); }
};

class BinaryOperator : public Expression {
protected:
  const Expression& leftOperand;
  const Expression& rightOperand;

public:
  BinaryOperator() = delete;
  BinaryOperator(const Expression& left, const Expression& right)
    : leftOperand{left}, rightOperand{right} {}
  BinaryOperator(Expression&& left, Expression&& right) // (2)
    : leftOperand(std::move(left)), rightOperand(std::move(right)) {}
  virtual std::string to_string() const = 0;
};

class PlusOperator : public BinaryOperator {
public:
  using BinaryOperator::BinaryOperator;
  virtual int evaluate() const {
    return leftOperand.evaluate() + rightOperand.evaluate();
  }
  virtual std::string to_string() const {
    return "(" + leftOperand.to_string() + "+" + rightOperand.to_string() + ")";
  }
};

和这个主要功能

int main(void) {
  Constant c1{5}, c2{10};
  PlusOperator p1{c1, c2};
  std::cout << p1.to_string() << " = " << p1.evaluate() << std::endl;

  PlusOperator p2{Constant{5}, Constant{10}};
  std::cout << p2.to_string() << " = " << p2.evaluate() << std::endl; // (1)
}

编译没有问题(g++ -std=c++17)。但是,如果我使用 -fsanitize=address 标志进行编译,程序会在点 (1) 处终止。当我想调用 p2.to_string() 时根据 gdb。我假设,我在 (2) 处做错了,对象没有正确 stored/lifetime 扩展。

所以我的具体问题是:如何将临时对象绑定到我的 Expression-Ref 而不会使地址清理器失败?什么是替代品?

提前致谢!

So my concrete question is: how is it possible to bind a temporary object to my Expression-Ref without failing the address-sanitizer?

你不能。临时对象在完整表达式的末尾被销毁,除非您使用对 const 的函数局部引用或函数局部右值引用来捕获它们。您 class 成员不是对 const 的函数局部引用或函数局部右值引用,因此没有临时生命周期延长。