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循环在内部就这样做了。