Как эффективно связать lvalue или rvalue с одной и той же ссылкой? - PullRequest
0 голосов
/ 09 февраля 2019

Скажем, у вас есть функция C ++, которая использует измененную версию параметра (const).

MyObject alter_obj( MyObject const & obj ); // Creates new, altered object

void func( MyObject const & original ) {
    MyObject const & altered( alter_obj( original ) );
    // ...
}

Это работает должным образом, из-за продления времени жизни временного из-за "наиболее важного const",Это также довольно эффективно, если alter_obj() соответствует требованиям для оптимизации возвращаемого значения, поскольку RVO означает, что измененный объект, возвращаемый по значению, не будет скопирован без необходимости.

Это также будет эффективно, если вы не внесете изменение вall:

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 , а не только номинальному типу.Это означает, что когда берется ложная ветвь (без изменений), создается временное значение, вызывая конструктор копирования MyObject в original.Если копировать MyObject нетривиально, это может привести к снижению производительности из-за создания этой «ложной» копии.

Есть ли хороший способ обойти это?Можно ли эффективно связать локальную ссылку с другой существующей ссылкой или с временной (выбор на основе значений времени выполнения) без создания дополнительных копий?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Может быть добавление второго параметра к func()?

void func( MyObject const& original, bool modify = false ) {
    if ( modify )  MyObject const & altered( alter_obj( original ) );
    else MyObject const & not_altered( original ); 
}

Может достичь того, что вы ищете ...

0 голосов
/ 09 февраля 2019

Я бы создал отдельную функцию, которая принимает ссылку и вызывает ее, например:

void func( MyObject const & original ) {
    if (apply_alteration)
        func_internal(alter_obj(original));
    else
        func_internal(original);
}

void func_internal( MyObject const & possibly_altered) {
    // ...
}
...