Вопрос об использовании std :: move () при перегрузке членов - PullRequest
0 голосов
/ 01 сентября 2018

Этот вопрос возник из C ++ Primer (5-е издание) , последняя тема Имитация виртуальной копии в главе 15.

Определить два классифицированных по наследству:

class Quote{
public:
virtual Quote* clone() const & {return new Quote(*this);}
virtual Quote* clone() && {return new Quote(std::move(*this));}
//other members
};

class Bulk_quote: public Quote{
public:
Bulk_quote* clone() const& {return new Bulk_quote(*this);}
Bulk_quote* clone() && {return new Bulk_quote(std::move(*this));}
//other members
    };

и класс, использующий их:

class {
public:
  void add_item(const Quote& sale)   //copy the given object
    { items.insert(std::shared_ptr<Quote>(sale.clone()));}
  void add_item(Quote&& sale)  //move the given object
    {items.insert(std::shared_ptr<Quote>(std::move(sale).clone()));}
//other memebers
private:
  static bool compare(const std::shared_ptr<Quote>& lhs,const std::shared_ptr<Quote>& rhs)
{return lhs->isbn() < rhs->isbn();}
std::multiset<std::shared_ptr<Quote>,decltype(compare)*> items(compare);
};

Я застрял в двух наблюдениях:

(1), почему std::move(*this) в определении члена virtual Quote* clone()&&? Насколько я понимаю, эта версия может быть запущена только с изменяемым значением (скажем, временные объекты) под ссылочным квалификатором &&. Может ли std::move(*this) быть заменен на *this?

(2) Аналогично (1), почему std::move(sale) во втором определении члена add_item, который может быть запущен только для объекта rvalue. Для rvalue ссылка Quote&& sale может быть связана только с rvalue, необходимо ли std::move(sale)?

Для вызова второй версии add_item книга гласит: «хотя тип продажи является ссылочным типом rvalue, продажа (как и любая другая переменная) является lvalue». Однако, версия void add_item(const Quote& sale) будет вызвана, если sale является lvalue. Кто может мне помочь?

1 Ответ

0 голосов
/ 01 сентября 2018

Вы, кажется, путаете объекты с выражениями. Категория значений (lvalue или rvalue) является свойством выражения, а не объекта, поэтому даже если, например, *this относится к временному объекту, оно , поскольку выражение все еще является lvalue. Так же, как и sale.

Существуют сложные правила, чтобы определить, является ли выражение lvalue или rvalue. Соответствующие правила для вашего примера:

  • выражение вида *expr всегда является lvalue;

  • безусловное имя переменной в качестве выражения всегда является lvalue.

...