Скажем, у вас есть функция C++, которая использует измененную версию параметра (const).
MyObject alter_obj( MyObject const & obj ); // Creates new, altered object
void func( MyObject const & original ) {
MyObject const & altered( alter_obj( original ) );
// ...
}
Это работает правильно из-за продления срока службы временного объекта из-за «самой важной константы». Также довольно эффективно, если alter_obj()
отвечает требованиям оптимизации возвращаемого значения, поскольку RVO означает, что измененный объект, возвращаемый значением, не копируется без необходимости.
Также было бы эффективно, если бы вы вообще не вносили изменения:
void func( MyObject const & original ) {
MyObject const & not_altered( original );
// ...
}
Дополнительные ссылки на данный объект в основном бесплатны, без каких-либо потерь производительности при создании копии.
Но скажем, требования немного меняются, и вы хотите решить, вносить изменения или нет, в зависимости от условий выполнения. Наивно я ожидал, что использование тернарного оператора для объединения двух предыдущих подходов будет эффективным, связывая исходный объект напрямую, когда это возможно, или связывая временный, если нет.
MyObject alter_obj( MyObject const & obj ); // Creates new, altered object
void func( MyObject const & original ) {
// ...
MyObject const & possibly_altered(
apply_alteration ?
alter_obj( original ) :
original
);
// ...
}
Однако оказалось, что этот подход не так эффективен, как хотелось бы. Тернарный оператор, по-видимому, требует, чтобы последние два параметра соответствовали статусу lvalue/rvalue, а не только номинальному типу. Это означает, что при выборе ветви false (без изменений) временное значение rvalue создается путем вызова конструктора копирования MyObject на original
. Если MyObject не является тривиальным для копирования, существует потенциальная потеря производительности из-за создания этой «ложной» копии.
Есть ли хороший способ обойти это? Можно ли эффективно привязать локальную ссылку либо к другой существующей ссылке, либо к временной (выбор на основе значений времени выполнения) без создания дополнительных копий?