【问题标题】:confusion overloading memberfunctions on rvalues and lvalues右值和左值上的混淆重载成员函数
【发布时间】:2016-06-22 19:59:57
【问题描述】:

我有以下设置:

struct foo
{
    void bar( ) &  { std::cout << "lvalue\n"; }
    void bar( ) && { std::cout << "rvalue\n"; }

    ~foo( ) { bar( ); }
};


int main( int arg, char **argv )
{
    foo{ }.bar();
}

导致输出

rvalue
lvalue

我不明白 dtor 的输出总是lvalue 不管我怎么努力。虽然我同意取地址 类似于

(*this).bar( ); // sure enough this will print lvalue

调用 lvalue-overload 我不明白为什么我永远无法得到 rvaluefor dtor 的输出。

我觉得这很奇怪,因为对象首先是一个右值,并且在被破坏之前以某种方式绑定到一个左值。这是怎么回事?

【问题讨论】:

  • 你错过了跟踪构造函数。
  • ...foo( ) { bar( ); }

标签: c++ lvalue rvalue overload-resolution


【解决方案1】:

this是prvalue,而*this是lvalue,自然会调用lvalue ref-qualifiers:

§ 5.3.1 Unary operators [expr.unary.op]

一元*运算符执行间接:应用它的表达式应该是一个指向 对象类型,或指向函数类型的指针,结果是引用对象或函数的 左值 表达式指向的位置。

来自 cppreference,this pointer

当在允许 this 关键字的任何上下文(非静态成员函数体、成员初始化器列表、默认成员初始化器)中使用非静态类成员时,隐式 this-> 会自动添加在名称之前,产生成员访问表达式(如果成员是虚拟成员函数,则产生虚函数调用)。

注意:调用 this-> 等价于调用 (*this)。

#include <iostream>

struct foo
{
    void bar( ) &  { std::cout << "lvalue\n"; x(); }
    void bar( ) && { std::cout << "rvalue\n"; x(); }

    void x( ) & { std::cout << "x lvalue\n"; }
    void x( ) && { std::cout << "x rvalue\n"; }

    ~foo( ) { bar( ); }
};


int main( int arg, char **argv )
{
    foo{ }.bar();
}

打印:

rvalue
x lvalue
lvalue
x lvalue

如果出于某种原因,您确实想调用右值函数,则可以将 this 指针强制转换为右值引用:

~foo( ) { static_cast<foo&&>(*this).bar( ); }

或者使用std::move:

~foo( ) { std::move(*this).bar( ); }

【讨论】:

  • 感谢您的详细说明。这是否意味着在允许 this 的上下文中(基本上在包括 ctor 和 dtor 在内的所有成员函数中),对象将被视为左值,而外部值类别可以不同? (已投票但还没有足够的代表)。
  • @david 是的。简单地使用它,显式或隐式将调用左值引用限定符。添加了一个解决方案来调用右值引用限定符。
  • no - 我不想强制调用右值重载。我只是感到困惑,该对象似乎是一个右值,而客户端代码会产生这个输出。然而,dtor 说左值对我来说似乎很奇怪,因为同一个对象是右值和左值,这取决于是否调用了成员函数
  • 感谢您的澄清!任何转发“外部”价值类别的方式? (只是感兴趣,还没有用例,可能会在那里使用非成员函数)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2020-08-24
相关资源
最近更新 更多