C++ 通过ref限定符重载运算符是否合理,以防止临时性?

C++ 通过ref限定符重载运算符是否合理,以防止临时性?,c++,ref-qualifier,C++,Ref Qualifier,我刚刚想到,operator+&co可以对这个进行操作,以获得右值;i、 e.给定一个类C,可以这样做: class C { // ... C operator-( const C& rhs ) const & { C result = *this; result -= rhs; return result; } C&& operator-( const C& rhs ) &a

我刚刚想到,
operator+
&co可以对
这个
进行操作,以获得右值;i、 e.给定一个类
C
,可以这样做:

class C {
    // ...
    C operator-( const C& rhs ) const & {
        C result = *this;
        result -= rhs;
        return result;
    }
    C&& operator-( const C& rhs ) && {
        *this -= rhs;
        return std::move( *this );
    }
};
这将通过简单地就地修改临时值来防止复制


这会像我期望的那样吗?这是一种合理的优化,还是编译器会创建同样快的代码?

让我们只包装
std::string
,然后执行一个简化版的
操作符+

struct C { 
    std::string val;

    C&& operator+(const C& rhs) && {
        val += rhs.val;
        return std::move(*this);
    }   

    std::string::iterator begin() { return val.begin(); }
    std::string::iterator end() { return val.end(); }
};
有了这些,这就很好了:

for (char c : C{"hello"}) { .. }
表达式的范围将延长临时表达式的生存期,所以我们可以。但是,考虑一下:

for (char c : C{"hello"} + C{"goodbye"}) { .. }
我们实际上有:

auto&& __range = C{"hello"}.operator+(C{"goodbye"});
在这里,我们不将临时绑定到引用。我们正在绑定一个引用。对象的生存期没有延长,因为。。。它不是一个物体。所以我们有一个悬而未决的引用和未定义的行为。这对于那些期望这一点起作用的用户来说是非常令人惊讶的:

for (char c : std::string{"hello"} + std::string{"goodbye"}) { .. }
您必须返回一个值:

C operator+(const C& rhs) && {
    val += rhs.val;
    return std::move(*this);
}

这就解决了这个问题(因为现在我们有了临时扩展),如果移动对象比复制对象便宜,这就是一个胜利

在第一个版本中,您已经可以获得副本省略。所以我不确定是否需要第二个(如果它真的有效,我觉得它会咬你的屁股,但我可能错了)是的,我有一种感觉,复制省略可能会导致类似的性能。。。但我还不知道我的版本怎么会咬我的屁股。(但我不确定,这就是问题所在。)对象生存期问题<代码>C&&C=C()-一些
c
悬空。你似乎是对的。我还不太明白为什么。@KyleStrand在半空中暂停这个临时文件,如果它是不可移动的类型,就延长它的寿命。您很少显式地需要它,但基于范围的for循环在内部就这样做了。