Есть ли какой-либо реальный вариант использования для спецификаторов функций?
Недавно я узнал о function reference qualifiers
, например.
struct foo
{
void bar() {}
void bar1() & {}
void bar2() && {}
};
Где мне может понадобиться эта функция, существует ли какой-либо реальный прецедент для этой языковой функции?
Ответы
Ответ 1
В основном два использования:
- Чтобы обеспечить оптимизированную перегрузку, например, чтобы перемещать элемент из временного объекта, а не копировать его.
-
Предотвращение неправильного использования API. Например, никто не ожидал бы
int a = 1 += 2;
и это также вызовет ошибку компиляции. Однако
string b = string("foo") += "bar";
является законным, если operator +=
объявлен как
string & operator += (string const & o);
как это обычно бывает. Также у этого есть неприятный побочный эффект предоставления lvalue-reference для вашего rvalue. Плохая идея. Это можно легко предотвратить, объявив оператор как
string & operator += (string const & o) &;
Ответ 2
Где мне может понадобиться эта функция, существует ли какой-либо реальный прецедент для этой языковой функции?
Пример, который вы показываете, довольно бесполезен, он более полезен, когда у вас есть перегруженная функция, одна версия, которая работает с lvalues и одна, которая работает с rvalues.
Рассмотрим тип, немного похожий на 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()&&