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

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

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

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

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

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

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

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

const std::string* const ps = f(); -- почему не хочет компилироваться (компилится лишь при использовании new для выделения памяти)?
...
Рейтинг: 0 / 0
28.10.2012, 14:45
    #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
28.10.2012, 14:54
    #38016104
ayvango
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
Спасибо,

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

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

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

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

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

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


Да.

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


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


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


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

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

Что значит нельзя ? Можно, но просто он уже станет невалидным.
...
Рейтинг: 0 / 0
28.10.2012, 21:13
    #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
28.10.2012, 21:17
    #38016332
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
ayvangoСпасибо,

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

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

Понял ты неправильно. Ссылка или указатель -- всё равно. Важно, что функция возвращает.
Если ссылку или указатель, это не влияет на время жизни объекта, которым они проинициализированы
при возврате. Если значение -- то значение и возвращается, при этом объект копируется.
...
Рейтинг: 0 / 0
28.10.2012, 21:46
    #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
29.10.2012, 06:31
    #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
29.10.2012, 16:38
    #38017368
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
ayvangoв VisualStudio всё копмилируется, только вот для f1() и f2() стоят предупреждения о возвращении ссылки на локальную переменную. Вопрос в том, будет ли это корректно работать?Нет, не будет.
Добавь в свой класс деструктор с printf/cout, добавь после каждой команды в своем примере печать строк "сделано это" и посмотри когда именно вызываются деструкторы.
...
Рейтинг: 0 / 0
29.10.2012, 18:36
    #38017582
ayvango
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
посмотри когда именно вызываются деструкторы
Деструкторы для e1 и e2 вызываются почти сразу же, причём сначала вызывается деструктор для e1, затем для e2. Означает ли это, что при выходе из ф-и f1() и f2() соответственно соответствующие объекты уничтожаются несмотря на то, что на них указывает ссылка? Почему ссылка не продлевает время жизни объекта? И почему для встроенных типов (int) случаи со ссылками работают?
...
Рейтинг: 0 / 0
29.10.2012, 20:46
    #38017736
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
ayvangoпосмотри когда именно вызываются деструкторы
Деструкторы для e1 и e2 вызываются почти сразу же, причём сначала вызывается деструктор для e1, затем для e2. Означает ли это, что при выходе из ф-и f1() и f2() соответственно соответствующие объекты уничтожаютсяДа.
ayvango несмотря на то, что на них указывает ссылка?Ссылки и указатели никак не влияют на время жизни объектов.
ayvangoИ почему для встроенных типов (int) случаи со ссылками работают?А они не работают. Ссылка на уничтоженный int продолжает существовать и до тех пор пока никому не понадобилось место где раньше был записан этот int в той ячейке памяти будет записано старое значение. И его даже можно будет использовать.... Но как только другая функция потребует память - твоя ссылка начнет показывать на память занятую совсем другим значением.
У элементарных типов нету деструкторов поэтому ты просто не видишь когда они уничтожаются, но на самом деле правила уничтожения и у объектов и у элементарных типов одинаковые.
...
Рейтинг: 0 / 0
29.10.2012, 21:04
    #38017753
ayvango
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
А вот тут тогда почему всё работает?

http://alenacpp.blogspot.ru/2008/01/const.html
...
Рейтинг: 0 / 0
29.10.2012, 21:55
    #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
29.10.2012, 22:49
    #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
29.10.2012, 22:59
    #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
29.10.2012, 23:03
    #38017823
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Объясните раз и навсегда про возвращение из функции указателя и ссылки
ayvango
в VisualStudio всё копмилируется, только вот для f1() и f2() стоят предупреждения о возвращении ссылки на локальную переменную. Вопрос в том, будет ли это корректно работать?

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


Да.



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

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

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

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


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