powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Объясните раз и навсегда про возвращение из функции указателя и ссылки
25 сообщений из 45, страница 1 из 2
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38015993
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Допустим, есть какая-то функция.Предполагается, что поток только один.

1)Может ли она возвращать указатель на объект, созданный внутри неё?
2)Меняет ли что-то, если объект статический, создан внутри ф-и?

Те же вопросы для случая, когда возвращается указатель на константу либо константный указатель.
Те же вопросы для случая, когда возвращается ссылка.
Те же вопросы для случая, когда возвращается ссылка на константу.

На вопрос 2) я бы ответил, что возвращать ссылку на статический объект, определённый внутри ф-и можно во всех случаях, только надо следить, чтобы всё корректно работало. А что с 1) ?
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38015994
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если объект создан динамически (в куче), то можно, если на стеке, то нельзя
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016015
Фотография vromanov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть облась жизни, есть облась видимости. Тут надо проверять область жизни.
Все созданное на стеке живет только до выхода из функции.
Созданное в динамической памяти, в пулах живет пока не будет освобождено. Поэтому возвращать можно. Если памать, кончено, не освобождается внутри функции.
Статические пременные живут вечно. Так что указатели на них также можно возвращать. Для однопоточных приложений вполне толковый механизм.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016033
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Cerebrum и vromanov,

Правильно ли я понял, что все Ваши ответы следует понимать следующим образом:
При возвращении константного/неконстантного указателя/ссылки на статический объект, определённый внутри функции, всё будет работать нормально, если всё правильно записать?
При возвращении константного/неконстантного указателя/ссылки на нестатический объект надо, чтобы нестатический объект создавался в куче?
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016073
Фотография vromanov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango,

Да
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016078
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо, кажется, разобрался.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016092
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А Вы пишите, что если объект не является статическим, он должен создаваться в куче. Но вот пример

...
std::string f(){ return "abc"; }
...
const std::string& s = f();
...

Здесь всё нормально, а объект не является статическим. Как это объяснить? И почему то же самое не верно для указателей?

const std::string* const ps = f(); -- почему не хочет компилироваться (компилится лишь при использовании new для выделения памяти)?
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016100
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoА Вы пишите, что если объект не является статическим, он должен создаваться в куче. Но вот пример

...
std::string f(){ return "abc"; }
...
const std::string& s = f();
...

Здесь всё нормально, а объект не является статическим. Как это объяснить? И почему то же самое не верно для указателей?

const std::string* const ps = f(); -- почему не хочет компилироваться (компилится лишь при использовании new для выделения памяти)?
В первом случае, когда функция производит возврат, создается копия возвращаемого объекта

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
int Add(int a, int b)
{
	int result = a + b;
	return result; 
}

// создается временная копия result, которая при помощи механизмов языка,
// существует ровно столько сколько необходимо для передачи ее значения
// внешней переменной
int nC = Add(231, 36); // адрес nC != адресу result, но содержимое одинаково (конструктор копирования)

// если такой переменной нет, копия сразу же разрушается
Add(231, 36); // result после return не существует, он никому (кроме отладчика) НЕ нужен!



В случае указателя

Код: plaintext
1.
2.
3.
4.
5.
int* Add(int a, int b)
{
	int result = a+b;
	return &result;
}


Память по которой расположен result жива пока выполняется функция Add. Как только произошел возврат из Add все переменные созданные на стеке в функции Add разрушаются, а значит адрес result, теперь указывает на какой-то абстрактный мусор.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016104
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо,

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

а в случае с константным указателем на кностанту передаются обломки (указатель на разрушенный объект), потому всё и отказывается компилироваться.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016218
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoСпасибо,

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

а в случае с константным указателем на кностанту передаются обломки (указатель на разрушенный объект), потому всё и отказывается компилироваться.Нет. Если писать так:
Код: plaintext
1.
2.
3.
4.
5.
int& Add(int a, int b)
{
	int result = a+b;
	return result;
}

, то тоже получится фигня. Смотрите на то, что возвращает функция, а не на то, чему это возвращаемое значение присваивается.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016320
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoДопустим, есть какая-то функция. Предполагается, что поток только один.

1)Может ли она возвращать указатель на объект, созданный внутри неё?


Да.

ayvango2)Меняет ли что-то, если объект статический, создан внутри ф-и?


Т.е. может ли функция вернуть указатель на статический объект, область видимости которого -- эта функция ?
Да, может.
Вообще, функция в С++, которая возвращает по своей сигнатуре указатель какого-то типа, может возвращать
любое валидное выражение типа "указатель на этот тип", С++ никак не ограничивает функцию ни в чём.
Другое дело, что по семантике например бессмысленно возвращать указатель на автоматический объект, созданный
в этой функции -- он будет удалён по выходу из этой функции, и указатель автоматом станет невалидным.


ayvangoТе же вопросы для случая, когда возвращается указатель на константу либо константный указатель.
Те же вопросы для случая, когда возвращается ссылка.
Те же вопросы для случая, когда возвращается ссылка на константу.


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

Это я к тому, что возможно ты неправильно сформулировал вопрос. Лучше было бы, если бы ты привёл все интересующие тебя варианты кода, тогда можно было бы их прокомментировать и сказать, где имеет смысл так делать, а где нет.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016323
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CerebrumЕсли объект создан динамически (в куче), то можно, если на стеке, то нельзя

Что значит нельзя ? Можно, но просто он уже станет невалидным.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016328
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoА Вы пишите, что если объект не является статическим, он должен создаваться в куче. Но вот пример

...
std::string f(){ return "abc"; }
...
const std::string& s = f();
...

Здесь всё нормально, а объект не является статическим. Как это объяснить?


Ну здесь -то нет указателей, здесь объект по значению возвращается.
Им инициализируется константная ссылка, это по стандарту продлевает жизнь временного объекта на время
жизни этой ссылки.

ayvango И почему то же самое не верно для указателей?
const std::string* const ps = f(); -- почему не хочет компилироваться (компилится лишь при использовании new для выделения памяти)?

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

Это если функция f выглядит как

std::string f(){ return "abc"; }

если же как

std::string* f(){ return new std::string("abc"); }

то проблема в том, что указатель НЕ продлевает время жизни объекта, в отличие от ссылки.
Но собвтсенно и объект-то не возвращается, возвращается указатель на него.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016332
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoСпасибо,

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

а в случае с константным указателем на кностанту передаются обломки (указатель на разрушенный объект), потому всё и отказывается компилироваться.

Понял ты неправильно. Ссылка или указатель -- всё равно. Важно, что функция возвращает.
Если ссылку или указатель, это не влияет на время жизни объекта, которым они проинициализированы
при возврате. Если значение -- то значение и возвращается, при этом объект копируется.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016344
AbstractionayvangoСпасибо,

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

а в случае с константным указателем на кностанту передаются обломки (указатель на разрушенный объект), потому всё и отказывается компилироваться.Нет. Если писать так:
Код: plaintext
1.
2.
3.
4.
5.
int& Add(int a, int b)
{
	int result = a+b;
	return result;
}

, то тоже получится фигня. Смотрите на то, что возвращает функция, а не на то, чему это возвращаемое значение присваивается.

А так работает?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int& Add(int a, int b)
{
	int result = a+b;
	return result;
}

int main() {
 int &res = Add(1, 2);
 std::cout << res;
}
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38016472
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivЛучше было бы, если бы ты привёл все интересующие тебя варианты кода, тогда можно было бы их прокомментировать и сказать, где имеет смысл так делать, а где нет.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
class Example
{
   int i;
   std::string s;
public:
   Example(int j) : i(j), s("abc"){};
};


const Example& f1(){ return Example(1); }
Example& f2(){ return Example(2); }
const Example* f3(){ return new Example(3); }
Example* f4(){ return new Example(4); }


int main(){
   const Example& e1 = f1();
   Example& e2 = f2();
   const Example* e3 = f3();
   Example* e4 = f4();

   delete e3;
   delete e4;
}



в VisualStudio всё копмилируется, только вот для f1() и f2() стоят предупреждения о возвращении ссылки на локальную переменную. Вопрос в том, будет ли это корректно работать?
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017368
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoв VisualStudio всё копмилируется, только вот для f1() и f2() стоят предупреждения о возвращении ссылки на локальную переменную. Вопрос в том, будет ли это корректно работать?Нет, не будет.
Добавь в свой класс деструктор с printf/cout, добавь после каждой команды в своем примере печать строк "сделано это" и посмотри когда именно вызываются деструкторы.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017582
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
посмотри когда именно вызываются деструкторы
Деструкторы для e1 и e2 вызываются почти сразу же, причём сначала вызывается деструктор для e1, затем для e2. Означает ли это, что при выходе из ф-и f1() и f2() соответственно соответствующие объекты уничтожаются несмотря на то, что на них указывает ссылка? Почему ссылка не продлевает время жизни объекта? И почему для встроенных типов (int) случаи со ссылками работают?
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017736
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoпосмотри когда именно вызываются деструкторы
Деструкторы для e1 и e2 вызываются почти сразу же, причём сначала вызывается деструктор для e1, затем для e2. Означает ли это, что при выходе из ф-и f1() и f2() соответственно соответствующие объекты уничтожаютсяДа.
ayvango несмотря на то, что на них указывает ссылка?Ссылки и указатели никак не влияют на время жизни объектов.
ayvangoИ почему для встроенных типов (int) случаи со ссылками работают?А они не работают. Ссылка на уничтоженный int продолжает существовать и до тех пор пока никому не понадобилось место где раньше был записан этот int в той ячейке памяти будет записано старое значение. И его даже можно будет использовать.... Но как только другая функция потребует память - твоя ссылка начнет показывать на память занятую совсем другим значением.
У элементарных типов нету деструкторов поэтому ты просто не видишь когда они уничтожаются, но на самом деле правила уничтожения и у объектов и у элементарных типов одинаковые.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017753
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот тут тогда почему всё работает?

http://alenacpp.blogspot.ru/2008/01/const.html
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017784
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvangoА вот тут тогда почему всё работает?

http://alenacpp.blogspot.ru/2008/01/const.html Потому что автор статьи видит звон, но не понимает где он.
const там совершенно не причем. А вот то что строка задана как "abc" это важно.
Задние констант в коде это совершенно отдельная тема. Задумайся, где эта строка "abc" хранится? В куче или на стеке?
Что происходит когда я пишу:
Код: plaintext
1.
2.
3.
void foo() {
   char *s = "abc";
}

?
Компилятор самопроизвольно добавит конструктор string? или strcpy? Где лежит "abc"? Может ли она быть затерта вызовом другой функции?
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017809
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А так работает?Abstractionпропущено...
Нет. Если писать так:
Код: plaintext
1.
2.
3.
4.
5.
int& Add(int a, int b)
{
	int result = a+b;
	return result;
}

, то тоже получится фигня. Смотрите на то, что возвращает функция, а не на то, чему это возвращаемое значение присваивается.

А так работает?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
int& Add(int a, int b)
{
	int result = a+b;
	return result;
}

int main() {
 int &res = Add(1, 2);
 std::cout << res;
}



Нет. Хотя если тестировать, то иногда может казаться, что оно работает.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017817
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
class Example
{
   int i;
   std::string s;
public:
   Example(int j) : i(j), s("abc"){};
};


const Example& f1(){ return Example(1); } // компилируется, не работает.
Example& f2(){ return Example(2); } // не компилируется, не работает.
const Example* f3(){ return new Example(3); } // компилируется, не работает. (нельзя будет удалить объект)
Example* f4(){ return new Example(4); } //  компилируется, работает.


int main(){
   const Example& e1 = f1();
   Example& e2 = f2();
   const Example* e3 = f3();
   Example* e4 = f4();

   delete e3;
   delete e4;
}





Вообще при таких проблемах часто нужно подумать о возврате объекта по значению.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017823
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango
в VisualStudio всё копмилируется, только вот для f1() и f2() стоят предупреждения о возвращении ссылки на локальную переменную. Вопрос в том, будет ли это корректно работать?

Это не должно компилироваться по стандарту. Если студия это жрет, это проблемы частного компилятора.
...
Рейтинг: 0 / 0
Объясните раз и навсегда про возвращение из функции указателя и ссылки
    #38017828
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Означает ли это, что при выходе из ф-и f1() и f2() соответственно соответствующие объекты уничтожаются несмотря на то, что на них указывает ссылка?


Да.



Почему ссылка не продлевает время жизни объекта?

Ссылка может продлить время жизни только локального временного объекта, а тут ты выходишь из функции вообще.
Верни объект по значению, он скопируется наружу, и все будет ок.

И почему для встроенных типов (int) случаи со ссылками работают?

Не работают и так, и так. Если ты гоняеш тесты какие то, то это тебе только кажется, что оно работает.
...
Рейтинг: 0 / 0
25 сообщений из 45, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Объясните раз и навсегда про возвращение из функции указателя и ссылки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]