Привязать rvalue ref к lvalue ref члену класса - PullRequest
0 голосов
/ 06 марта 2020

У меня есть следующие определения

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). По словам GDB, когда я хочу позвонить p2.to_string(). Я предполагаю, что я делаю что-то не так в (2), и объект не сохранен должным образом / время жизни увеличено.

Итак, мои конкретные вопросы: как можно привязать временный объект к моему Expression-Ref? без сбоев адрес-дезинфицирующее средство? Какие есть альтернативы?

Заранее спасибо!

1 Ответ

1 голос
/ 06 марта 2020

Итак, мой конкретный вопрос: как можно привязать временный объект к моему Expression-Ref, не отказав в очистке адреса?

Вы не можете. Временные значения уничтожаются в конце полного выражения, если только вы не захватите их с локальной ссылкой функции на константную или локальную ссылку на функцию. Вы, члены класса, не являетесь функциональными локальными ссылками на константные или функциональные локальные rvalue-ссылки, поэтому временного продления жизни не существует.

...