Понимание оптимизации возвращаемого значения и возврат временных файлов - C++

Значок имеет тип набора и оператор случайного элемента, унарный"?", таким образом, выражение

? set( [1, 2, 3, 4, 5] )

произведет случайное число между 1 и 5.

случайное семя инициализируется к 0, когда программа запущена, так для приведения к различным результатам на каждом использовании выполнения randomize()

23
задан James McNellis 13 July 2010 в 17:26
поделиться

4 ответа

В Два первых случая будут иметь место оптимизация RVO. RVO - это старая функция, и большинство компиляторов ее поддерживают. Последний случай - это так называемый NRVO (названный RVO). Это относительно новая функция C ++. Стандарт позволяет, но не позволяет Это требует реализации NRVO (а также RVO), но некоторые компиляторы поддерживают его.

Вы можете прочитать больше о RVO в пункте 20 книги Скотта Мейерса More Effective C ++. 35 новых способов улучшить ваши программы и дизайн .

Вот хорошая статья о NRVO в Visual C ++ 2005.

16
ответ дан 29 November 2019 в 02:46
поделиться

Все случаи верны. Все они построят временный объект и применит конструктор копирования возвращаемого типа. Обязательно, если нет конструктора копирования, код завершится ошибкой.

RVO произойдет во всех трех случаях в большинстве компиляторов. Единственное отличие - последний, где стандарт не требует этого. Это потому, что у вас есть именованная переменная. Но большинство компиляторов достаточно умны, чтобы применять к ней RVO ... чем позже объявляется именованная переменная и чем меньше преобразований она применяется, тем больше шансов, что RVO будет применен к именованной переменной.

Между прочим, возврат ссылка, конечно, возможна, как вы могли видеть в другом коде. Чего вы не должны делать, так это возвращать ссылку на локальный объект.

std::string& get_a_string2()
{
    std::string str("hello");
    return str; //error!
}

Как вы знаете, вызовет ошибку времени компиляции. Однако

std::string& get_a_string2(std::string& str)
{
    // do something to str
    return str; //OK
}

будет работать нормально. В этом случае здесь не используется конструкция или копирование. Просто функция возвращает ссылку на свой аргумент.

2
ответ дан 29 November 2019 в 02:46
поделиться
  1. Это зависит от вашего компилятора - о какой платформе вы имеете в виду? Лучший способ выяснить это - скомпилировать очень небольшое тестовое приложение и проверить ASM, создаваемый вашим компилятором.

  2. Да, это нормально, хотя вы никогда не упоминаете, что вас беспокоит; скорость? стиль? вы можете создать локальный временный объект для ссылки на константу - время жизни временного будет увеличено до времени жизни ссылки - попробуйте и убедитесь сами! (Херб Саттер объясняет это здесь ) См., Например, конец сообщения.

ИМО, вам почти всегда лучше доверять компилятору, чтобы он оптимизировал ваш код для вас. Очень мало случаев, когда вам нужно заботиться о подобных вещах (очень низкоуровневый код - одна из таких областей, где вы взаимодействуете с аппаратными регистрами).

int foo() { return 42; }

int main(int, char**)
{
    const int &iRef = foo();
    // iRef is valid at this point too!
}
1
ответ дан 29 November 2019 в 02:46
поделиться

Во-первых, вполне нормально вернуть временное значение по значению, что вы и делаете. Он копируется, и хотя оригинал выходит за пределы области видимости, копия этого не делает и может безопасно использоваться вызывающим.

Во-вторых, все три случая фактически идентичны (поскольку вы не получаете доступ к временному в в любом случае третий случай), и компилятор может даже выдать один и тот же код для всех из них. Следовательно, он может использовать RVO во всех трех случаях. Это полностью зависит от компилятора.

7
ответ дан 29 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: