【问题标题】:Question about the usage of std::move() in member overloading关于成员重载中使用 std::move() 的问题
【发布时间】:2018-09-01 06:41:07
【问题描述】:

本题来自C++ Primer(5th Edition),第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()&amp;&amp; 的定义中?据我了解,此版本只能在引用限定符&amp;&amp; 下的可修改右值(例如时间对象)上运行。可以将std::move(*this) 替换为*this

(2)与(1)类似,为什么std::move(sale)在成员add_item的第二个定义中只能在右值对象上运行。对于右值引用Quote&amp;&amp; sale只能绑定右值,std::move(sale)有必要吗?

对于调用add_item 的第二个版本,书中说“虽然 sale 的类型是右值引用类型,但 sale(像任何其他变量一样)是左值”。但是,如果sale 是左值,则将调用版本void add_item(const Quote&amp; sale)。谁能帮帮我?

【问题讨论】:

  • 只要有名字(包括this),它就被当作左值处理。你可以在函数中多次使用this,你不希望第一个擦除对象......所以当你准备放弃对象时,你必须用std::move这样说。参数上的&amp;&amp; 是让调用者调用正确的版本,但在内部它与&amp; 基本相同。 l/rvalue 不是对象的属性,而是你如何引用它。

标签: c++ rvalue-reference dynamic-binding


【解决方案1】:

您似乎将对象与表达式混淆了。值类别(左值或右值)是表达式的属性,而不是对象的属性,因此即使 *this 指的是临时对象,它作为表达式仍然是左值. sale也是如此。

有复杂的规则来确定表达式是左值还是右值。您的示例的相关规则是:

  • *expr 形式的表达式始终是左值;

  • 作为表达式的变量的非限定名称始终是左值。

【讨论】:

    猜你喜欢
    • 2021-08-17
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多