Форум программистов, компьютерный форум CyberForum.ru

Касательно указателей и ссылок. - C++

Восстановить пароль Регистрация
 
Андрей2011
29 / 23 / 2
Регистрация: 18.01.2011
Сообщений: 359
30.01.2012, 12:12     Касательно указателей и ссылок. #1
Цитирую фразу из популярной ныне книги Айвора Хортона.
"Никогда не возвращайте из функции ссылку на локальную переменную"
Так вот. Не понятно почему так категорично все. По моему даже оч. удобно создать лок. переменную, присвоить ей ссылку на объект. поработать с ним. переменную удалить. Я вот подобным образом свою программу делаю. Озадачила меня эта вот фраза. Прошу помощи в разъяснении данного вопроса.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
dimcoder
Полярный
 Аватар для dimcoder
449 / 422 / 66
Регистрация: 11.09.2011
Сообщений: 1,108
30.01.2012, 12:13     Касательно указателей и ссылок. #2
Ну все путем практики осваивается
Локальный объект - он на то и локальный - что бы потом и "самоликвидироваться" после выхода за область действия. А вы, понимаете, того, использовать его намереваетес.
Если прям надо, просто верните обеъкт, не указатель\ссылку.
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
30.01.2012, 12:18     Касательно указателей и ссылок. #3
Цитата Сообщение от Андрей2011 Посмотреть сообщение
"Никогда не возвращайте из функции ссылку на локальную переменную"
Цитата Сообщение от Андрей2011 Посмотреть сообщение
создать лок. переменную, присвоить ей ссылку на объект. поработать с ним. переменную удалить.
Это два разных высказывания. Вы уж определитесь.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.01.2012, 12:42     Касательно указателей и ссылок. #4
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
 
class Foo
{
public:
    Foo(int foo):
    m_foo(new int(foo))
    {
    }
 
    Foo(const Foo& source):
    m_foo(new int(source.foo()))
    {
    }
 
    ~Foo()
    {
        delete m_foo;
    }
 
    int foo() const
    {
        return *m_foo;
    }
 
private:
    int *m_foo;
};
 
Foo& bar()
{
    Foo res(10);
 
    return res;
}
 
int main()
{
    std::cout << bar().foo() << std::endl; // Ooops!
 
    return 0;
}
Добавлено через 8 минут
Вот так понагляднее будет:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
 
class Foo
{
public:
    Foo(int foo):
    m_foo(new int(foo))
    {
        std::cout << "Foo::Foo(int) : " << m_foo << std::endl;
    }
 
    Foo(const Foo& source):
    m_foo(new int(source.foo()))
    {
        std::cout << "Foo::Foo(const Foo&) : " << m_foo << std::endl;
    }
 
    ~Foo()
    {
        std::cout << "Foo::~Foo() : " << m_foo << std::endl;
        
        delete m_foo;
    }
 
    int foo() const
    {
        return *m_foo;
    }
 
private:
    int *m_foo;
};
 
Foo& bar()
{
    std::cout << "Foo& bar() : before Foo res(10);" << std::endl;
    Foo res(10);
    std::cout << "Foo& bar() : after Foo res(10);" << std::endl;
    
    std::cout << "Foo& bar() : res.foo() : " << res.foo() << std::endl;
    
    return res;
}
 
int main()
{
    std::cout << "int main() : before Foo goo = bar();" << std::endl;
    Foo goo = bar();
    std::cout << "int main() : after Foo goo = bar();" << std::endl;
    
    std::cout << "int main() : goo.foo() : " << goo.foo() << std::endl; // Ooops!
 
    return 0;
}
Вывод:
Код
int main() : before Foo goo = bar();
Foo& bar() : before Foo res(10);
Foo::Foo(int) : 0x5c0e78
Foo& bar() : after Foo res(10);
Foo& bar() : res.foo() : 10
Foo::~Foo() : 0x5c0e78
Foo::Foo(const Foo&) : 0x5c0e78
int main() : after Foo goo = bar();
int main() : goo.foo() : 6041520
Foo::~Foo() : 0x5c0e78
Обратить внимание на строку 7. Деструктор вызывается до копирования объекта. Беда!
Байт
 Аватар для Байт
14004 / 8835 / 1234
Регистрация: 24.12.2010
Сообщений: 16,014
30.01.2012, 12:46     Касательно указателей и ссылок. #5
Айвор Хортон неточен
Вот такой код вполне допустим (проверено)
C
1
2
3
4
5
char *foo(int n)
{ static char s[10];
    itoa(n, s, 10);
    return &s[0];
}
Вот если бы s была без слова static, тогда Ой.
Андрей2011
29 / 23 / 2
Регистрация: 18.01.2011
Сообщений: 359
30.01.2012, 14:14  [ТС]     Касательно указателей и ссылок. #6
Цитата Сообщение от dimcoder Посмотреть сообщение
Если прям надо, просто верните обеъкт, не указатель\ссылку.
Ну он же копируется тогда? Блин.(((
Вот мой код:
C++
1
2
3
4
5
6
7
8
9
10
    
//сначала я создаю массив объектов TTo4ka;
//ф-я GetPoint - ищет нужный объект.
.
.
.
//тут вот, отдельная ф-я. я создаю локальный объект типа TTo4ka
//дабы присвоить ей, нейденый с помощью ф-и GetPoint объект.
TTo4ka To4ka;
    To4ka =  GetPoint(X,Y);
//тут есть еще вот какие моменты:
//1.ф-я GetPoint -возвращает ссылку на объект TTo4ka
//ибо чтоб не копировалась не создавалась.
//2.если буду возвращать не ссылку а объект то будет тогда копироваться!!
//3.если принимает ссылку не созданный локальный объект то программа ругается.
//4. TTo4ka To4ka; - это тоже плохо. т.к. у меня создаются новые объекты типа TTo4ka в //локальной ф-и. Или не плохо это?
dimcoder
Полярный
 Аватар для dimcoder
449 / 422 / 66
Регистрация: 11.09.2011
Сообщений: 1,108
30.01.2012, 14:23     Касательно указателей и ссылок. #7
Цитата Сообщение от Андрей2011 Посмотреть сообщение
4. TTo4ka To4ka; - это тоже плохо. т.к. у меня создаются новые объекты типа TTo4ka в //локальной ф-и. Или не плохо это?
Кто вам такое сказал? Ну что ж теперь вообще не создавать ничего в функциях?

Не по теме:

А то оперативка расплавиться



Короче вот пример:
C++
1
2
3
4
5
int& func()         //Оч плохо
{
   int x = 19;
   return *x;
}
Это то что вы хотите сказать/сделать?
Или так:
C++
1
2
3
4
5
int& func(int *x)   //Хорошо
{
   *x = 19;
   return x;
}
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.01.2012, 14:27     Касательно указателей и ссылок. #8
Цитата Сообщение от Андрей2011 Посмотреть сообщение
//1.ф-я GetPoint -возвращает ссылку на объект TTo4ka
Насколько я помню по предыдущей теме, проблем быть не должно, поскольку GetPoint ищет точку не в локальном массиве, следовательно, и ссылку она возвращает на не локальный (по отношению к ней) объект.
Цитата Сообщение от Андрей2011 Посмотреть сообщение
//2.если буду возвращать не ссылку а объект то будет тогда копироваться!!
Если это вопрос, то да. Если констатация факта... не знаю, что сказать
Цитата Сообщение от Андрей2011 Посмотреть сообщение
//3.если принимает ссылку не созданный локальный объект то программа ругается.
Нифига не понял
Цитата Сообщение от Андрей2011 Посмотреть сообщение
//4. TTo4ka To4ka; - это тоже плохо. т.к. у меня создаются новые объекты типа TTo4ka в //локальной ф-и. Или не плохо это?
Всё относительно. Плохо-не плохо... Сразу не сказать. Если функция выглядит так:
C++
1
2
3
4
5
6
void func()
{
    TTo4ka a;
    TTo4ka b;
    TTo4ka c;
}
тогда конечно плохо, ибо создаются три объекта, которые потом никак не используются. А если так:
C++
1
2
3
4
5
6
void func()
{
    TTo4ka a;
    
    // Что-то делаем с объектом a для того, чтобы получить какие-то реальные результаты
}
то ничего плохого в локальном объекте нет.
Андрей2011
29 / 23 / 2
Регистрация: 18.01.2011
Сообщений: 359
30.01.2012, 14:30  [ТС]     Касательно указателей и ссылок. #9
не совсем. вернее совсем нет. )) Ф-я выглядит так:
C++
1
2
3
4
5
6
7
 TTo4ka &GetPoint(const short &X,const short &Y)
{
 short Nom = p_MassivTo4ek[X][Y]; //просто указатель на массив хранящий номер 
                                                //объекта по точкам Х и Y
 return p_To4ka[Nom-1];  //указатель на массив объектов. Можно их считать глобальными
                                   //т.к. под них выделена память динамическая.
}
Суть вопроса заключается в том что хочу, после нахождения нужного объекта в ф-и, вернуть его,
или его ссылку, или указатель на объект, дабы в другой ф-и можно было с ним работать. изменять
и т.п. Но! Но хотелось бы все это действо провернуть ПРАВИЛЬНО не тратя лишней памяти и т.п.
dimcoder
Полярный
 Аватар для dimcoder
449 / 422 / 66
Регистрация: 11.09.2011
Сообщений: 1,108
30.01.2012, 14:33     Касательно указателей и ссылок. #10
Цитата Сообщение от Андрей2011 Посмотреть сообщение
return p_To4ka[Nom-1]; *//указатель на массив объектов. Можно их считать глобальными
* * * * * * * * * * * * * * * * * *//т.к. под них выделена память динамическая.
Это вы называете "возвратить локальную переменную"!?!?

И почему если под переменную выделена память динамически, она вдруг становиться глобальной?!?

Цитата Сообщение от Андрей2011 Посмотреть сообщение
short Nom = p_MassivTo4ek[X][Y]; //просто указатель на массив хранящий номер
nom - не указатель
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.01.2012, 14:34     Касательно указателей и ссылок. #11
Андрей2011, не всегда не тратя памяти значит правильно. Например,если в классе хранится строка, я предпочту в геттере вернуть её копию, а не константную ссылку на неё. Потому что константность легко можно отменить и прострелить себе ногу. Хотя всё, конечно, зависит от задачи (точнее даже, от требований).
Андрей2011
29 / 23 / 2
Регистрация: 18.01.2011
Сообщений: 359
30.01.2012, 14:43  [ТС]     Касательно указателей и ссылок. #12
Вот. Увжаемый, silent_1991, меня понял. Пусть и отчасти))
Просто получается вот какая штука. Объект TTo4ka содержит в себе штук 10 переменных и еще 2 массива по 4 элемента в каждом.
А теперь представьте.
Человек ставит "точку" (ход делает) и запусается эта ф-я. локальная. которая локально создает 4 такие вот точки потом их удаляет естественно. Т.е. ... память выделилась и она же вернулась. Но правильно ли это? все же на создание одного объекта уходит много байт.
и я в книге Айрона Хортона сегодня прочитал что он в примере в своем делает такую штуку:
Он, из ф-и возвращает ссылку на объект а принимает её, ссылку, указатель!
т.е. как-то так:
C++
1
2
    TTo4ka *To4ka;
    *To4ka =  GetPoint(X,Y);
- и тогда, предполагаю, лишние объекты не создаются. А указатель потом можно и обнулить.

Добавлено через 5 минут
Цитата Сообщение от dimcoder Посмотреть сообщение
Это вы называете "возвратить локальную переменную"
- это я называю возвратом ссылки на объект.

Цитата Сообщение от dimcoder Посмотреть сообщение
nom - не указатель
- имелось ввиду что p_MassivTo4ek - указатель на массив.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.01.2012, 14:45     Касательно указателей и ссылок. #13
Андрей2011, я не совсем понял, о чём вы (как указатель может "принять" ссылку), но суть приёма снова не понимаю. Факт в том, что функции предназначены для выполнения некоторых локальных действий либо для преобразования информации. И возвращать из функции новый объект зачастую единственно правильное решение.
Андрей2011
29 / 23 / 2
Регистрация: 18.01.2011
Сообщений: 359
30.01.2012, 14:48  [ТС]     Касательно указателей и ссылок. #14
вот:
C++
1
2
    TTo4ka *To4ka;
    To4ka =  &GetPoint(X,Y);
не совсем понял что написал...но по крайней мере програма работает (не проверял на сколько правильно) и не создает новых объектов!
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
30.01.2012, 14:49     Касательно указателей и ссылок. #15
Андрей2011, а какая здесь разница между ссылкой и указателем (кроме отбрасывания синтаксических прелестей ссылок и вновь появившейся возможностью выстрелить себе в ногу)?
AzaKendler
 Аватар для AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
30.01.2012, 15:06     Касательно указателей и ссылок. #16
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
struct Unit
{
    int a;
 
    Unit(int v):a(v){};
    Unit():a(0){};
    ~Unit(){};
 
    Unit& operator +=(Unit& u)
    {
        a+=u.a;
        return *this;
    }
    Unit& operator = (Unit& u)
    {
        a= u.a;
        return *this;
    }
 
};
 
Unit&& test (Unit&& a)
{
    Unit a2;
    a2+=a;
    return std::forward<Unit> (a2);//возвращается reference только rvalue
};
 
 
int main()
{
    Unit u = test(Unit(10));
    return 0;
}
давайте обсудим. может и не совсем в тему. но все про возврат ссылок на локальные или временные объекты из тела функции. что думаете по этим нововведениям? плюсы очевидны, дополнительных объектов создано не будет. Но все таки что насчет этой темы - возврат ссылок. Разве с новым стандартом не стоит уточнить, что нельзя возвращать lvalu reference на временный объект. Я прав?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.01.2012, 15:10     Касательно указателей и ссылок.
Еще ссылки по теме:

Реализация программы с использованием ссылок и указателей C++
Ступор в возврате указателей и ссылок C++
C++ Демонстрация работы ссылок, указателей или дескрипторов

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Андрей2011
29 / 23 / 2
Регистрация: 18.01.2011
Сообщений: 359
30.01.2012, 15:10  [ТС]     Касательно указателей и ссылок. #17
о как замутил. О_о
Yandex
Объявления
30.01.2012, 15:10     Касательно указателей и ссылок.
Ответ Создать тему
Опции темы

Текущее время: 08:59. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru