Программистское абстрактное
Aug. 24th, 2012 11:40 amДано:
using std::string;
string dotted_pair1(const string & a, const string & b) {
return a + '.' + b;
}
string dotted_pair2(const string & a, const string & b) {
return (a + '.') += b;
}Как нетрудно видеть умозрительно, да и экспериментально, dotted_pair2 эффективнее - меньше временных объектов создается. В общем случае компилятор не имеет права делать такую оптимизацию автоматически. Как бы ему объяснить, что в этом конкретном случае он его имеет?
Ну и совсем абстрактно: интересно, программисты на ФЯП в принципе задумываются о зависимости эффективности выполняемого кода от идиоматики исходного, или они выше этих глупостей?
no subject
Date: 2012-08-24 06:52 pm (UTC)no subject
Date: 2012-08-24 06:55 pm (UTC)no subject
Date: 2012-08-24 07:03 pm (UTC)no subject
Date: 2012-08-24 07:10 pm (UTC)no subject
Date: 2012-08-24 07:11 pm (UTC)gcc 4.7.1: апсолютно адинхуй.
Почему второй вариант вообще проходит — на первый взгляд непонятно.
no subject
Date: 2012-08-24 07:17 pm (UTC)Я тоже пробовал с опаской, но видимо, потому что r-values нельзя лишь передавать по неконстантным ссылкам, а применять к ним неконстантные методы - можно.
no subject
Date: 2012-08-24 07:21 pm (UTC)Различия только вот в чём:
В первом случае пускается конструктор на временную строку с аргументом a, к ней цепляется одна точка, и ей же инициируется возврат, к возврату цепляется b. Деструктор на временную строку, выход из функции.
Во втором случае пускается конструктор на временную строку с аргументом a, к ней цепляется одна точка, к ей же цепляется b, ей же инициируется возврат. Деструктор на временную строку, выход из функции.
Возможно, из-за того, что конкатенации (append()) и конструктору приходится работать с разными данными, в профилировании может набежать разница. Но это уже от твоих данных зависит, а не от компилятора.
no subject
Date: 2012-08-24 07:22 pm (UTC)Я проверил VC2010 - практически идентичные варианты. По числу объектов совершенно одинаковые - один временный, где конкатенируются строки. Разница только в том что во втором случае временный объект создается явно внутри функции, а в первом через move внутри второго оператора конкатенации.
no subject
Date: 2012-08-24 07:29 pm (UTC)no subject
Date: 2012-08-24 07:31 pm (UTC)no subject
Date: 2012-08-24 07:33 pm (UTC)no subject
Date: 2012-08-24 07:44 pm (UTC)no subject
Date: 2012-08-24 07:46 pm (UTC)no subject
Date: 2012-08-24 07:52 pm (UTC)no subject
Date: 2012-08-24 08:00 pm (UTC)no subject
Date: 2012-08-24 08:01 pm (UTC)no subject
Date: 2012-08-24 08:08 pm (UTC)конкатенации (append()) и конструкторам приходится работать с разными данными, в профилировании может набежать разница.
О том и речь. И разница всегда будет в пользу второго случая. У меня на GCC 4.4.0 на моем тесте 10%.
В 4.7, наверное, уже вовсю C++11 с rvalue references, но это ж с дуба можно рухнуть все комбинации аргументов выписывать. Мой вопрос вот в чём: неужели ничего более удобного нельзя в языке придумать, чтобы объяснить компилятору, чё те надо?
no subject
Date: 2012-08-24 08:16 pm (UTC)a + '.' + b => operator+(operator+(a, '.'), b)
(a + '.') += b => (operator+(a,'.')).operator+=(b)
no subject
Date: 2012-08-24 08:17 pm (UTC)F(const a, b) ≡ unique_copy(a).F(b), а не через повторения одного и того же с помощью rvalue references? Бешеная репликация кода в инклюдах задолбала.
no subject
Date: 2012-08-24 08:17 pm (UTC)no subject
Date: 2012-08-24 08:26 pm (UTC)string dotted_pair(const string & a, const string & b) { string tmp(a); return tmp.append(1, '.').append(b); }Или для любителей one-liners и obfuscation:
string dotted_pair(const string & a, const string & b) { return (a + '.').append(b); }Временных объектов и конструторов/деструкторов во всех четырёх случаях ровно одинаково.
no subject
Date: 2012-08-24 08:30 pm (UTC)внешний оператор конкатенации с сигнатурой :
string operator+(string&&, const string&)
no subject
Date: 2012-08-24 08:37 pm (UTC)string dotted_pair(const string & a, const string & b) {
return string(a).append(1, '.').append(b);
}
по объектам опять все едино, но теоретически append() чуть быстрее, потому что не обернут снаружи оператором. Хотя скорее всего, при оптимизации все это и так уберется
no subject
Date: 2012-08-24 08:38 pm (UTC)no subject
Date: 2012-08-24 08:42 pm (UTC)