Если вы думаете о обычае, двигаться с поддержкой класса строки, надлежащим образом использовать любую комбинацию категорий значений аргумента:
S operator+(S const& lhs, S const& rhs);
S operator+(S && lhs, S const& rhs);
S operator+(S const& lhs, S && rhs);
S operator+(S && lhs, S && rhs);
Функция возвращает prvalue вместо xvalue. Возвращение xvalues , как правило, очень опасная вещь – std :: move and std :: forward - очевидные исключения. Если вы должны были вернуть ссылку RValue вы разобьете код, как:
for (char c : my_string + other_string) {
//...
}
Эта петля ведет себя (в соответствии с 6.5.4/1 в N3092), а если код:
auto&& range = my_string + other_string;
Это в свою очередь, приводит к обманутой ссылке. Срок службы временного объекта не продлевается, потому что ваш оператор + не возвращает prvalue. Возвращение объектов по значению отлично. Это создаст временные объекты, но эти объекты имеют значения rvalues, поэтому мы можем украсть их ресурсы, чтобы сделать их очень эффективными.
Во-вторых, ваш код не должен также составить по той же причине, что это не будет компилироваться:
int&& foo(int&& x) { return x; }
Внутри тела функции х является Левое и вы не можете инициализировать «возвращаемое значение» (в данном случае ссылку rvalue) с выражением lvalue. Итак, вам нужен явный приведение.
В-третьих, вам не хватает константы & + const & перегрузка. Если оба аргумента равны lvalues, компилятор не найдет в вашем случае пригодного для использования оператора +.
Если вы не хотите так много перегрузок, можно был бы написать:
S operator+(S value, S const& x)
{
value += x;
return value;
}
Я намеренно не писал return value+=x;
, потому что этот оператор, вероятно, возвращает Lvalue ссылку, которая привела бы скопировать строительство возвращаемое значение. С двумя строками, которые я написал, возвращаемое значение будет двигаться, построенное из значения .
S x = a + b + c + d;
По крайней мере, этот случай является очень эффективным, потому что нет лишнего копирования участвует даже если компилятор не может игнорировать копии – благодаря ходу с поддержкой строки класса. На самом деле, с классом, как станд :: строки вы можете использовать свою функцию-член быстрой подкачки и сделать его эффективным в C++ 03, а также при условии, у вас есть достаточно умный компилятор (как GCC):
S operator+(S value, S const& x) // pass-by-value to exploit copy elisions
{
S result;
result.swap(value);
result += x;
return result; // NRVO applicable
}
См Давид Статья Авраама Want Speed? Pass by Value. Но эти простые операторы не будут столь эффективными Дано:
S x = a + (b + (c + d));
Здесь левая рука оператора всегда именующий. Так как оператор + берет свою левую сторону по значению, это приводит ко многим копиям. Четыре перегрузки сверху тоже отлично справляются с этим примером.
Прошло некоторое время с тех пор, как я прочитал старый рассказ Линуса. Если он жаловался на ненужные копии в отношении std :: string, эта жалоба более недействительна в C++ 0x, но раньше она вряд ли была действительной. Вы можете эффективны конкатенация много строк в C++ 03:
S result = a;
result += b;
result += c;
result += d;
Но в C++ 0x можно также использовать оператор + и зЬй :: двигаться. Это тоже будет очень эффективно.
Я действительно посмотрел исходный код Git и его управление строкой (strbuf.h). Это выглядит хорошо продумано. За исключением функции отсоединения/присоединения, вы получаете то же самое с поддержкой std :: string с поддержкой перехода с очевидным преимуществом, что ресурс, который он автоматически управляет самим классом, в отличие от пользователя, которому необходимо запомнить правильные функции на правильные времена (strbuf_init, strbuf_release).
Не задано в вопросе: если этого набора достаточно, это означает, что у нас есть 3 новых перегрузки для каждого оператора ... И кроме использования Boost.Operator я не вижу возможности автоматически их генерировать. Из верхней части моей головы это означает 8 'operator +' для 'std :: string' из-за' std :: string' и 'char const *' mix ... –
Ух, это ужасно. И они называют это «решением».Pfft –
@ litb: Я согласен с вашим чувством ... особенно когда я думаю о '-',' * ','/'и всех других подобных операторах. У числовых классов будет гораздо больше оснований наследовать от 'boost :: addable' и co, я думаю. –