函数的引用限定符是否有真正的用例?

19
最近我了解了关于函数的引用限定符,例如。
struct foo
{
    void bar() {}
    void bar1() & {}
    void bar2() && {}
};

在哪些情况下我可能需要这个功能?这个语言特性有没有实际的用例呢?

相关:https://dev59.com/eWoy5IYBdhLWcg3wWss_ - Caramiriel
3
我知道的最有用的方法是使用 类型转换运算符 重载 struct foo { operator std::string () const & { return s; } operator std::string () && { return std::move(s); } std::string s; };。因此,foo func() { return {"string"s}; } ... std::string s = foo(); 不会涉及非必要的拷贝和销毁操作,可以避免对非空 std::string 对象的操作。 - Tomilov Anatoliy
@Orient 请将这段话作为答案添加,因为它非常有趣,可能对某些人有帮助。 - tommyk
2个回答

29

在我可能需要这个特性的情况下,这个语言特性有什么真正的用例吗?

你展示的例子相当无用,当你有一个重载函数时,它更有用,其中一个版本操作 lvalue,另一个版本操作 rvalue。

考虑一种类型,类似于 std::stringstream,它拥有一个字符串并按值返回它。如果对象是一个 rvalue,则可以移动字符串而不是复制它。

class StringBuilder
{
public:
  std::string get() const& { return m_str; }
  std::string get() && { return std::move(m_str); }

private:
  std::string m_str;
};

这意味着当您从函数返回一个StringBuilder并想要获取其中的字符串时,您不需要复制:

std::string s = buildString().get();

更一般地,假设有一个函数f(const X&),如果使用f(X&&)重载它会很有用,那么对于一个成员函数X::f(),将其改为X::f() const&并将其与 X::f()&& 进行重载可能是有用的。


18

基本上有两种用途:

  1. 提供优化的负载,例如将成员移出临时对象而不必复制它。
  2. 防止API的误用。例如,没有人会期望

int a = 1 += 2;

继续工作将导致编译错误。

string b = string("foo") += "bar";

operator +=如果被声明为

是合法的。
string & operator += (string const & o);

通常情况下就是这样。此外,这会产生一个让您的rvalue具有左值引用的不良副作用。这是个坏主意。可以通过将运算符声明为来轻松避免这种情况

string & operator += (string const & o) &;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接