Здравствуйте, watchmaker, Вы писали:
К>>Возврат значения — это и есть немного подержать стек
К>>Альтернативное решение — передать буфер в функцию, как параметр. В том числе, как дефолтный параметр, но там придётся повыкручиваться.
К>>Я не сторонник такого трюкачества, но вдруг пригодится.
W>Честно говоря, если прочитать например SystemV ABI, то можно увидеть, что это автоматически происходит для всех структур (размер которых больше некоторого порогового значения).
W>То есть всё это извращение с передачей дефолтного параметра не нужно.
Именно это я и имел в виду, — что возврат значения и есть придерживание стека. Вызывающая сторона сама размещает буфер и отдаёт его как неявный параметр.
W>Поэтому такой трюк с дефолтным параметром сугубо вредный: он явно выражает то, что и так записано в ABI как необходимое действие.
Насчёт сугубо-вредности — тут можно пообсуждать.
Во-первых, мы не надеемся на NRVO, а вручную гарантируем это. И заодно, снимаем требование о копируемости-перемещаемости с типа. (Правда, добавляя некоторую дефолтную инициализацию и вторую фазу).
Во-вторых, с этим же трюком мы можем отдавать буфер произвольного вида. Ну самое простое,
#include <iostream>
#include <cstring>
using namespace std;
template<int N> struct charholder { char buf[N]; };
int main() {
cout << strcat(strcat(strcpy(charholder<100>().buf,
"alfa"),
" + "),
"beta")
<< endl;
}
Здесь параметр не дефолтный, а очень даже явный, но суть та же.