Я не совсем уверен, что я понял, почему существует проблема, когда мы возвращаем ссылку локальной случайной величины
Поскольку стандарт C++ говорит, что это неопределенное поведение, если вы используете такую функцию и хотите избежать неопределенного поведения в вашей программе. То, что делает ваша программа, должно определяться правилами языка C++, а не быть случайным.
Обратите внимание, что вы возвращаете указатель, а не ссылку. Но в обоих случаях это неопределенное поведение.
Тогда обычный аргумент в том, что, когда функция используется, память переменной phantom
больше недоступна после выполнения код строки int phantom = 4;
поэтому он не может быть возвращен (по крайней мере, это является то, что Я понял до сих пор).
Это реализация ориентированной точка зрения и может помощи вам в понимании проблемы.
Тем не менее, важно различать наблюдаемое поведение программы и внутренние трюки компилятора для создания такого поведения. Вы даже не знаете, занята ли какая-либо память переменной в любом случае. Учитывая правило «как-если» и оптимизацию компилятора, вся функция, возможно, была удалена, даже если было определено поведение. Это всего лишь один пример того, что действительно может произойти за кулисами.
Но, в любом случае, это неопределенное поведение, так что все может случиться.
Вопрос в том, почему стандарт C++ не определяет поведение для случая, когда вы возвращаете такой указатель, а затем пытаетесь получить доступ к указателю? Ответом на это было бы то, что это не имеет смысла. Объект, названный локальной переменной phantom
, заканчивает свою жизнь, когда функция возвращается. Таким образом, у вас будет указатель на то, что больше не существует, но оно все еще является int*
, и разыменование не nullptr
int*
должно давать int
. Это противоречие, а стандарт C++ просто не утруждает себя решением такой бессмысленной ситуации.
Обратите внимание, что это наблюдение основано на правилах языка C++, не на проблемы реализации компилятора.
Почему в первом случае возникает ошибка компиляции, а во втором случае все работает?
Это, конечно, предупреждение и не ошибка, если ваши параметры компилятора не являются такими, что каждое предупреждение превращается в ошибку. Компилятор не должен отклонять код, потому что it's not ill-formed.
Тем не менее, ваш компилятор пытается быть полезным в первом случае, потому что он хочет, чтобы вы не создавали программу с неопределенным поведением.
Во втором случае поведение не определено. Возврат по значению означает, что копия сделана из объекта, который вы хотите вернуть. Копия создается до того, как оригинал будет уничтожен, а затем получатель получит эту копию. Это не бессмысленно и никак не противоречит, поэтому это безопасное и определенное поведение.
В первом случае возврат по значению не поможет вам, потому что хотя сам указатель is безопасно скопирован, его содержимое является тем, что в конечном итоге вызывает неопределенное поведение.
Указатель является ссылкой. Это просто не ссылка на C++. – xaxxon
@xaxxon Важное значение имеет правильная терминология :) –
@xaxxon: Технически ссылка похожа на указатель константы, не содержащий NULL. Но они имеют разную семантику и не должны быть объединены. Я бы сказал, что у Йоахима Пилеборга есть правильный ответ, но также стоит упомянуть, что в большинстве простых случаев, таких как NRVO, он ударит и удалит копию. Поэтому стоит просто вернуться к стоимости, пока вам не понадобится вернуть BigHonkingObject, который должен быть выделен в виде кучи. – djrollins