spamsink: (Default)
[personal profile] spamsink

Дано:
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 эффективнее - меньше временных объектов создается. В общем случае компилятор не имеет права делать такую оптимизацию автоматически. Как бы ему объяснить, что в этом конкретном случае он его имеет?

Ну и совсем абстрактно: интересно, программисты на ФЯП в принципе задумываются о зависимости эффективности выполняемого кода от идиоматики исходного, или они выше этих глупостей?
Page 1 of 4 << [1] [2] [3] [4] >>

Date: 2012-08-24 06:52 pm (UTC)
From: [identity profile] rezkiy.livejournal.com
мне всегда казалось, что как только больше двух слагаемых, надо использовать что-то типа stringstream.

Date: 2012-08-24 07:03 pm (UTC)
From: [identity profile] rezkiy.livejournal.com
Надо профайлить.

Date: 2012-08-24 07:11 pm (UTC)
From: [identity profile] dvv.livejournal.com
gcc 4.1.2: апсолютно адинхуй.
gcc 4.7.1: апсолютно адинхуй.

Почему второй вариант вообще проходит — на первый взгляд непонятно.

Date: 2012-08-24 07:21 pm (UTC)
From: [identity profile] dvv.livejournal.com
Именно глядя на ассемблер.

Различия только вот в чём:

В первом случае пускается конструктор на временную строку с аргументом a, к ней цепляется одна точка, и ей же инициируется возврат, к возврату цепляется b. Деструктор на временную строку, выход из функции.

Во втором случае пускается конструктор на временную строку с аргументом a, к ней цепляется одна точка, к ей же цепляется b, ей же инициируется возврат. Деструктор на временную строку, выход из функции.

Возможно, из-за того, что конкатенации (append()) и конструктору приходится работать с разными данными, в профилировании может набежать разница. Но это уже от твоих данных зависит, а не от компилятора.
Edited Date: 2012-08-24 08:02 pm (UTC)

Date: 2012-08-24 07:22 pm (UTC)
From: [identity profile] mynine.livejournal.com
А на чем вы тестировали?
Я проверил VC2010 - практически идентичные варианты. По числу объектов совершенно одинаковые - один временный, где конкатенируются строки. Разница только в том что во втором случае временный объект создается явно внутри функции, а в первом через move внутри второго оператора конкатенации.

Date: 2012-08-24 07:29 pm (UTC)
From: [identity profile] dvv.livejournal.com
В общем случае это так и есть. F(F(a,b),c) с точки зрения реализации ничем не отличается от, грубо говоря, a.F(b).F(c).

Date: 2012-08-24 07:33 pm (UTC)
From: [identity profile] dvv.livejournal.com
Ключевая фраза — "грубо говоря".

Date: 2012-08-24 07:44 pm (UTC)
From: [identity profile] mynine.livejournal.com
Чуть поторопился - в обоих случаях все-таки два объекта генерятся.

Date: 2012-08-24 07:46 pm (UTC)
From: [identity profile] cema.livejournal.com
В каком смысле исходного?

Date: 2012-08-24 07:52 pm (UTC)
From: [identity profile] mynine.livejournal.com
В данном случае (обоих примерах) конкатенация не метод, а свободная функция operator+() с константными параметрами. И с ней поэтому все проходит нормально.

Date: 2012-08-24 08:16 pm (UTC)
From: [identity profile] mynine.livejournal.com
это видимо в гнуси, в вижуале разворачиватся так (аргументы шаблона я выкинул для удобочитаемости - они const):

a + '.' + b => operator+(operator+(a, '.'), b)
(a + '.') += b => (operator+(a,'.')).operator+=(b)

Date: 2012-08-24 08:17 pm (UTC)
From: [identity profile] mynine.livejournal.com
Ну все равно, вряд ли тут можно обойтись всего одним объектом - первый дейстивтельно временный нужен для слияния строк, и второй это само возвращаемое значение.

Date: 2012-08-24 08:26 pm (UTC)
From: [identity profile] dvv.livejournal.com
Если у тебя такие данные, и важен порядок действий, то нужно не выёбываться, а указывать оный порядок действий:
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);
}

Временных объектов и конструторов/деструкторов во всех четырёх случаях ровно одинаково.
Edited Date: 2012-08-24 08:33 pm (UTC)

Date: 2012-08-24 08:30 pm (UTC)
From: [identity profile] mynine.livejournal.com
То, что я выше привел, (для первого примера) именно через rvalue ref реализовано.
внешний оператор конкатенации с сигнатурой :
string operator+(string&&, const string&)

Date: 2012-08-24 08:37 pm (UTC)
From: [identity profile] mynine.livejournal.com
уж лучше так ;)

string dotted_pair(const string & a, const string & b) {
return string(a).append(1, '.').append(b);
}

по объектам опять все едино, но теоретически append() чуть быстрее, потому что не обернут снаружи оператором. Хотя скорее всего, при оптимизации все это и так уберется

Date: 2012-08-24 08:38 pm (UTC)
From: [identity profile] dvv.livejournal.com
Это, видимо, цитата из стандарта. Но я отвечал не на тот вопрос, поэтому комментарий убран.

Date: 2012-08-24 08:42 pm (UTC)
From: [identity profile] dvv.livejournal.com
Это не "скорее всего", это уберётся в первую очередь.
Page 1 of 4 << [1] [2] [3] [4] >>

Profile

spamsink: (Default)
spamsink

February 2026

S M T W T F S
12345 67
8 91011 121314
15161718 192021
22 2324 25262728

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 5th, 2026 03:35 am
Powered by Dreamwidth Studios