Elision - это разрешение, предоставляемое разработчикам для использования несколькими значениями share, когда они кажутся разными значениями в коде.
std::string system_call(const char *cmd){
std::string a;
...
return a; // all return paths return `a` directly
}
std::string st = system_call("whatever code");
В приведенном выше случае, элизия означает, что a
, возвращаемое значение system_call
и st
все тот же объект.
Современные компиляторы elide, если вы не дадите им патологический флаг, чтобы сказать «не elide», когда это допускается стандартом и кодом. «Что делать, если это невозможно, когда это возможно» - это как спросить, что, если компилятор реализует целочисленное добавление в виде зацикленного приращения.
Оба варианта разрешены стандартом, и разумно ожидать.
Когда elision терпит неудачу (потому что ваш код делает невозможным), он возвращается к семантике перемещения в C++ 11. Для std::string
это означает, что при перемещении не происходит выделения памяти; в случае небольшой оптимизации строки некоторое количество символов может быть скопировано.
Elision может выйти из строя, если ваш код может вернуть заданную именованную переменную вдоль одного пути, а другой - по другому пути. Или, если вы вернете параметр функции.
Elision разрешен, если ваш оператор возврата return named_variable;
или return some_temporary_object;
, где возвращаемый объект соответствует типу возвращаемой функции. Это также разрешено, если вы делаете some_type bob = some_temporary;
, где some_temporary
является временным объектом типа some_type
. Аналогичным образом вы можете перейти в аргумент функции (но не из него).
Невозможно «гарантировать» разрешение.
C++ 17 делает почти все исключения из временных исключений выше обязательных.
Для того чтобы разрешить работу на C++ 14 и раньше, должен быть экземпляр или перемещать конструктор. Когда возникает элиция, она не называется, но она должна существовать. В C++ 17, когда временные «силы» устранены, конструктор копирования или перемещения не существует: временный объект не является отдельным объектом, а скорее предложением, которое представляет «как построить объект», что делается только позже.
Хорошо знать, что компилятор уже может это сделать. Но разве я могу заставить его это сделать? Swap, похоже, не работает, так как ему нужна не временная ссылка. – DarkZeros
Вы можете вызвать 'std :: move' в возвращаемом значении, но это предотвратит копирование по правилам стандарта, что еще более эффективно, чем перемещение. Если применяется небольшая оптимизация строк, перемещение из строки может, например, быть не намного эффективнее, если вообще. Я бы посоветовал не переезжать. Также, где вы хотите позвонить на своп? Личная оценка заключается в том, что возвращение по стоимости и полагаться на RVO позволит получить наиболее эффективное решение здесь. – midor
@DarkZeros Невозможно заставить компилятор не реализовывать 'a + = b' как' a = 0; for (int i = 0; i Yakk