diff btwn Функция, возвращающая переменную без ссылки и переменную ссылки по ссылке

0

рассмотрите приведенный ниже код

int& func1() {
    int x = 2;
    return x;
}

int& func2(int &x) {
    return x;
}

int main() {
    int x = func1();
    cout<<"\n : "<<x;
    int y = 3;
    x = func2(y);

    cout<<"\n : "<<x<<"\n";
}

вывод:

 : 2
 : 3

Код работает абсолютно нормально, но у меня мало сомнений, которые я перечислял ниже:

  1. В func1() я вернул переменную non_reference "x", но возвращаемый тип является ссылкой на int, поэтому как происходит преобразование и какая часть функции "x" действительно возвращается.

  2. В func1() "x" возвращается как ссылка, но является переменной стека, как можно вернуть ссылку x, я имею в виду, что после завершения не будет иметь значения (я отношу эту точку к логике "Функции не должны возвращать указатели, память которых распределена статически ").

  3. В func1() он возвращает переменную non refrence "x" как refrence для int и в func2() она возвращает переменную refernce "x" как refrence для int. Поскольку оба "x" имеют различный тип, но почему тип возврата тот же. ,

Я смущен, потому что я пытаюсь связать C++ с c, как в том, что все понятно, но здесь, в основном, из-за отсутствия описания макета памяти переменной refrence, поэтому, если кто-то может сказать об этом, тогда это будет очень полезно для меня

  • 0
    Один из них имеет неопределенное поведение. Поэтому код работает не совсем нормально.
  • 0
    Первый - неопределенное поведение, второй - нет. Это единственная разница, которая имеет значение.
Показать ещё 2 комментария
Теги:
reference
pass-by-reference

2 ответа

3
Лучший ответ

В func1, что вы возвращаете, является ссылкой на что-то. Это что-то x, которое является локальным для func1, чье время жизни заканчивается по возвращении. Затем, в main, вы назначаете содержимое указанной переменной (x func1, которая ест одуванчики корнями) для инициализации main локальной переменной x. Это неопределенное поведение, а это означает, что программе разрешено интерпретировать это как все, что угодно, форматирование жесткого диска или что-то еще. (скорее всего, func1 вернул указатель на переменную вызываемого стека, который, вероятно, все еще содержит правильное значение, потому что почему func1 значения в стеке, когда они будут раздавлены вызовом следующей функции?) В любом случае, программа должна быть скомпилирована с другими параметрами оптимизации, она может дать другой ответ.

В func2, что вы возвращаете, является ссылкой на что-то. Это то, на что ссылается x, которое относится к main y. Затем вы назначаете main x значение указанной переменной, которое равно y.

Что касается вашего вопроса о макете ссылок ссылок, то в C указатели являются адресами в памяти. Период. Побег невозможен. В C++ ссылки - это механизм более высокого уровня, где вы "обращаетесь к чему-то", "говорите о чем-то", "смотрите на меня прямо там". Они прекрасно реализуются как простые указатели. Но как языковая концепция, они немного более поддаются оптимизации, потому что они неизменны. (Как только ссылка установлена, ее нельзя изменить. И это относится к чему-то - даже к объекту с недопустимой ячейкой памяти). Поэтому стандарт не указывает хранилище для ссылок. Для свободы оптимизации.

ОБНОВЛЕНИЕ: Что касается вашего первого сомнения, main x является полнофункциональной переменной (она объявлена как таковая), а не ссылкой. Поэтому присвоение им любого другого значения не изменит значение y. В C++, когда вы оцениваете ссылку в выражении, например:

int x = 0;
int& y = x;

// Right hand side is the evaluation of the reference y
int z = y;

Он получает оценку на значение указанной переменной, то есть значение x, т.е. 0. А z - переменная, отличная от x.

Что касается вашего третьего сомнения, func2 вернет ссылку. Когда функция объявляется как возвращающая ссылку, то, что она возвращает, является ссылкой. Ссылка - это что-то, что говорит "Я там другой". В случае возвращаемого значения на уровне ассемблера при условии, что функция не включена и вызов действительно происходит, и так далее, то, что, скорее всего, будет возвращено func1 или func2 будет указателем на указанную переменную. На самом деле, в C++ ссылка на int - это тип того, что вы получаете, деферируя указатель int с помощью *. Сравните предыдущий примерный код с тем же кодом с указателями.

int x = 0;
int* const y = &x;

int z = *y;

С помощью ссылок & и * происходят молча.

Как вы знаете, в язык поддерживаются ссылки для поддержки перегрузки операторов, особенно оператора присваивания.

// Quizz : what is the type of (b = A(123))? What if it is a 1MB object?
// What should be the type of the right-hand side of the assignment operator?
A a, b;
a = b = A(123);

Это не может быть ценностью или это будет ужасно ужасно (передача результата копией). Это должен быть какой-то указатель, но этого не может быть. Там бы & или * где - то, в зависимости от того, как словом Standand для функциональности. Вместо того, чтобы изобретать множество специальных системных случаев перегрузки оператора, Stroustrup решил предоставить две ортогональные функциональные возможности: ссылки, которые являются неизменяемыми неизменяемыми указателями (и типом "говорить о переменной") и перегрузкой оператора, что чисто разрешено Рекомендации.

  • 0
    Вы объяснили мне второе сомнение, и я понял, но мое первое и третье сомнение до сих пор остается для меня загадкой. Далее со ссылкой на ваш второй абзац, если будут какие-либо изменения в основном х, будет ли это отражаться и на у, то есть, будет ли функция func2 возвращать значение или ссылку (это только часть моих сомнений) .. пожалуйста, разрешите мое нерешенное сомневается также
  • 0
    Обновлено с учетом ваших сомнений.
Показать ещё 3 комментария
0

Ссылка - это способ сделать два имени похожими на одну и ту же память. Возьмите эту функцию, например:

void something_cpp(int &x)
{
    x = 2;
}

Вы можете думать об этом в терминах C следующим образом:

void something_c(int *x)
{
    *x = 2;
}

аналогично функция, возвращающая ссылку в c++:

int something[10];

int &something2_cpp(void)
{
    return something[0];
}

int main(int argc, char *argv[])
{
    something2_cpp() = 10;
}

Об этом можно думать в C:

int something[10];

int *something2_c(void)
{
    return &something[0];
}

int main(int argc, char *argv[])
{
    *something2_c() = 10;
}
  • 0
    Во втором примере cpp я знаю, что это утверждение является распространенным, но я не знаю, как оно работает .. something2_cpp () = 10; а также * кое-что2_c () = 10; в третьем примере
  • 0
    main также мог бы сказать: int* p = something2_c(); *p = 10;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню