Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么是「;*此”的右值引用;对于_C++_C++11_Rvalue Reference - Fatal编程技术网

C++ 什么是「;*此”的右值引用;对于

C++ 什么是「;*此”的右值引用;对于,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,标准还为成员函数调用引用限定符的“this的右值引用”最典型的用例是什么 顺便说一句,关于这个语言特性有一个很好的解释 调用时,每个成员函数都有一个隐式对象参数,*此引用该参数 所以(a)这些正常函数重载: void f(const T&); void f(T&&); struct C { void f() const &; void f() &&; }; 调用时,如f(x);和(b)这些成员函数重载: void f(const

标准还为成员函数调用引用限定符的“this的右值引用”最典型的用例是什么


顺便说一句,关于这个语言特性有一个很好的解释

调用时,每个成员函数都有一个隐式对象参数,
*此
引用该参数

所以(a)这些正常函数重载:

void f(const T&);
void f(T&&);
struct C
{
    void f() const &;
    void f() &&;
};
调用时,如
f(x)
;和(b)这些成员函数重载:

void f(const T&);
void f(T&&);
struct C
{
    void f() const &;
    void f() &&;
};
当调用类似于
x.f()
-时,(a)和(b)都具有相似的生存能力和排名

因此,用例本质上是相同的。它们支持移动语义优化。在rvalue成员函数中,您基本上可以掠夺对象资源,因为您知道它是一个即将过期的对象(即将被删除):

例如:

struct C
{
    C operator+(const C& that) const &
    {
        C c(*this); // take a copy of this
        c += that;
        return c;
    }

    C operator+(const C& that) &&
    {
        (*this) += that;
        return move(*this); // moving this is ok here
    }
}

当对右值调用时,某些操作可能更有效,因此对
*的值类别进行重载可以自动使用最有效的实现,例如

struct Buffer
{
  std::string m_data;
public:
  std::string str() const& { return m_data; }        // copies data
  std::string str()&& { return std::move(m_data); }  // moves data
};
(此优化可针对
std::ostringstream
,但尚未正式提出。)

有些操作调用右值没有意义,因此在
*上重载此
可以删除右值表单:

int main()
{
    C c;
    c.f(); // lvalue, so calls lvalue-reference member f
    C().f(); // temporary is prvalue, so called rvalue-reference member f
    move(c).f(); // move changes c to xvalue, so again calls rvalue-reference member f
}
struct Foo
{
  void mutate()&;
  void mutate()&& = delete;
};
我还没有真正需要使用这个功能,但是现在我关心的两个编译器都支持它,也许我会发现它有更多的用途。

在我的编译器框架中(不久将发布)™), 将令牌等信息项传递到编译器对象中,然后调用
finalize
以指示流的结束

如果不调用
finalize
,就销毁一个对象是不好的,因为它不会清除所有的输出。但是
finalize
不能由析构函数完成,因为它会引发异常,同样,如果解析器已经中止,那么要求
finalize
获得更多输出也是错误的

在所有输入都已被另一个对象封装的情况下,最好将输入传递给右值编译器对象

pile< lexer, parser >( output_handler ).pass( open_file( "source.q" ) );
这为添加另一个重载提供了空间,该重载可以正确地完成对象。它是右值引用限定的,因此只有在对即将过期的对象调用时才会选中它

void pass( input_file f ) && {
    pass( std::move( f ) ); // dispatch to lvalue case
    finalize();
}
现在用户几乎不需要担心调用
finalize
,因为大多数编译器对象最终都被实例化为临时对象


注意,这类事情对于ref限定成员并不特殊。任何函数都可以对
t&
t&
单独重载。目前实际实现
pass
的方式是使用完美的转发,然后回溯来确定正确的语义:

template< typename compiler, typename arg >
void pass( compiler && c, arg a ) {
    c.take_input( a );

    if ( ! std::is_reference< compiler >::value ) {
        c.finalize();
    }
}
template
无效传递(编译器(&c,参数a){
c、 获取输入(a);
如果(!std::is_reference::value){
c、 定稿();
}
}

重载有很多方法。实际上,非限定成员函数不关心类别(左值或右值)是不寻常的调用它们的对象,而不是将该信息传递到函数中。除了隐式
this
之外的任何函数参数都必须说明其参数的类别。

现在编译器支持它,我希望很快会看到一两篇关于该主题的文章弹出。gcc只是在4.8.1中实现了它,所以没有太多的p人们已经开始使用这个功能了。基本上,只要你想让用户不创建类的永久对象,而只使用临时对象,你就可以通过创建所需的成员函数
&&
来实现这一点。对于你链接到的问题,示例和解释还不够吗?我看到弹出的一个常见示例是左值only>代码>运算符=< /代码>。类似于<代码> t和运算符=(t const &);将阻止<代码>()(t/);< />代码>编译。也考虑那些没有意义的成员调用rVals,如赋值运算符。@ DestMg:是的,rValor(PROVALUE或XVALUE)将不可绑定到<代码>空隙F(t&)。
,因此那里的用例与
T::f()相同&
w.r.t.隐式对象参数。我的主要观点是注意正常函数参数和隐式对象参数之间的正交关系-因此,当值类别和重载选择应用于正常函数参数时,对它们的一般理解可以重新调整用途,就像隐式对象参数的成员函数一样object参数(只有细微的差异不值得一提)。FWIW,我甚至不想为移动而烦恼。只需添加到自身,然后再移动。@R.MartinhoFernandes:这取决于移动构造函数和
操作符+=
实际做什么,但在某些情况下它可能更有效。已更改,谢谢。
操作符不应该吗+(…)&&
返回
C&&
以避免不必要的临时性?“对于未使用ref限定符声明的非静态成员函数,另一条规则适用:即使隐式对象参数不是const限定的,只要在所有其他方面参数可以转换为隐式对象参数的类型,右值也可以绑定到参数。”因此
Foo::mutate()
没有ref限定符对右值是可行的……关于排名:“S1和S2是引用绑定(8.5.3),都不引用未声明ref限定符的非静态成员函数的隐式对象参数,S1将右值引用绑定到右值,S2绑定左值引用。“。因此,在
mutate()no ref限定符
mutate()&&
之间使用右值将是不明确的。这是您的意图吗?即我认为您最终得到了想要的效果,但诊断可能不理想(错误模糊重载)。不,这不是我的意图,我只是在一个