Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как возвратить ссылку? Возвращение функцией ссылки на объект. 
V
    Опции темы
C/L
Дата 25.2.2009, 04:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Здравствуйте. Прочитал много инфы по ссылкам но так и не разобрался. В общем если имеется некоторая функция
Код

T& f1();
//первый вариант
T& f1(){
    T t;
    return t; // - ошибка t - локальная переменная
}
//второй вариант
T& f1(){
    T* pt = new T;
    return (*pt);
}

Второй вариант работает, но то что было с "new" надо где то "delete". А что если эту функцию использовать как параметр другой, тогда возможности запустить где-то delete вообще не будет. Для теста написал прогу:
Код

struct EXX; //испытуемый объект
struct EX_DATA; //запись о состоянии испытуемого объекта
typedef map<int, EX_DATA> EX_BOOK; //тип книги о жизни объектов
struct EXX{
    static EX_BOOK book; //книга живых и мертвых
    static void Hi_Exist(); //опрос объектов об их жизни
    void AddNewRef(); //добавление нового объекта в книгу жизни
    void DelRef(); //удаление из книги жизни, запись в книгу мертвых
    int id; //идентификатор объекта - его имя
    EXX(); //конструктор по умолчанию
    EXX(const EXX &exx); //конструктор копирования
    ~EXX(); //деструктор
};
struct EX_DATA{
    bool exist; //существует ли объетк
    EXX* pexx; //указатель на сам объект
    EX_DATA(){}; //конструктор по умолчанию
    EX_DATA(bool exist, EXX* pexx){this->exist = exist; this->pexx = pexx;};
};
void EXX::AddNewRef(){
    id = book.size() + 1; //даем объекту новое имя
    book[id] = EX_DATA(true,this); //записываем в книгу
}
void EXX::DelRef(){
    book[id].exist = false; //изменяем запись на мертвого
}
void EXX::Hi_Exist(){
    for (EX_BOOK::iterator iexx = book.begin(); iexx != book.end(); iexx++){ //проходим по всем записям
        if ((*iexx).second.exist) //если живой пусть назовет себя
            cout << (*iexx).first << ": Hi! I'm exist! My name: " << (*iexx).second.pexx->id << endl;
        else //даже если не живой пусть попробует назвать свое имя
            cout << (*iexx).first << ": Hi! I'm not exist! My name: " << (*iexx).second.pexx->id << endl;
    }
};
EXX::EXX(){ //конструктор по умолчанию
    AddNewRef(); //добавляем запись в книгу
    cout << "Create exx #" << id << endl; //сообщаем пользователю
}
EXX::EXX(const EXX &exx){ //конструктор копирования
    AddNewRef(); //добавляем запись в книгу
    cout << "Copy exx #" << id << endl; //сообщаем пользователю
}
EXX::~EXX(){ //деструктор
    DelRef(); //удаляем запись
    cout << "Delete exx #" << id << endl; //сообщаем пользователю
}
EX_BOOK EXX::book; //сама книга

EXX& cc(){EXX* exx = new EXX; return *exx; } //простая ф-ия возвращает ссылку на EXX
void dd(EXX exx){} //а эта использует EXX

void main(){
    for(int ii = 0; ii != 3; ii++) {
        dd(cc());
    }
    EXX::Hi_Exist();
}


На выходе получаем 3 живых объекта

Create exx #1
Copy exx #2
Delete exx #2
Create exx #3
Copy exx #4
Delete exx #4
Create exx #5
Copy exx #6
Delete exx #6
1: Hi! I'm exist! My name: 1
2: Hi! I'm not exist! My name: 13920463
3: Hi! I'm exist! My name: 3
4: Hi! I'm not exist! My name: 13920463
5: Hi! I'm exist! My name: 5
6: Hi! I'm not exist! My name: 13920463
PM MAIL WWW ICQ   Вверх
andrew_121
Дата 25.2.2009, 05:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

Репутация: 10
Всего: 33



C/L, Вопрос-то в чем?


--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
Lazin
Дата 25.2.2009, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



оба варианта неправильные, в первом случае ты возвращаешь ссылку на локальную переменную, которая после выхода из ф-ии перестанет существовать, ну а ссылка будет на несуществующий объект.
во втором случае, ты возвращаешь ссылку, там, где нужно вернуть указатель, конечно, можно вернуть и ссылку, но так никто не делает, так-как для того, что-бы потом удалить объект, все-равно нужен будет указатель 
PM MAIL Skype GTalk   Вверх
azesmcar
Дата 25.2.2009, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 52
Всего: 211



используй std::auto_ptr

Код

std::auto_ptr<T> f1() {
    return std::auto_ptr<T>(new T());
}

PM   Вверх
C/L
Дата 25.2.2009, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Поясню вопрос: можно ли создать внутри функции и вернуть по ссылке объект так, чтобы выйдя за пределы видимости он (объект) самоуничтожился, или точнее чтобы компилятор сгенерировал код уничтожения. Ведь в отличие от указателя, ссылка может ссылаться только на один объект и компилятор может отследить область ее видимости.

azesmcar, спасибо, попробую
PM MAIL WWW ICQ   Вверх
mes
Дата 25.2.2009, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(C/L @  25.2.2009,  08:16 Найти цитируемый пост)
можно ли создать внутри функции и вернуть по ссылке объект так, чтобы выйдя за пределы видимости он (объект) самоуничтожился, 

именно так и происходит, если создадите локальный объект, то выйдя за пределы видимости функции он уничтожится, и пользовать его нельзя будет - поэтому компилятор и против возвращения ссылки на него. Поэтому  нужно возвращать либо копию, либо умный указатель (auto_ptr, shared_ptr, ... в зависимости от потребностей)

Добавлено через 1 минуту и 6 секунд
P.S.можно еще вернуть ссылку на аргумент, переданный по ссылке.


--------------------
PM MAIL WWW   Вверх
C/L
Дата 25.2.2009, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Цитата(mes @ 25.2.2009,  11:56)
если создадите локальный объект, то выйдя за пределы видимости функции он уничтожится, и пользовать его нельзя будет

Да, согласен. Но я имел ввиду обасть видимости той переменной, куда эта ссылка вернется. Так ведь происходит когда мы вызываем конструктор. Например для моей тестовой программы:
Код

for(int ii = 0; ii != 3; ii++) {EXX &exx = EXX();}

выдает:
Create exx #1
Delete exx #1
Create exx #2
Delete exx #2
Create exx #3
Delete exx #3
1: Hi! I'm not exist! My name: 3
2: Hi! I'm not exist! My name: 3
3: Hi! I'm not exist! My name: 3

Значит вместо функции надо писать конструктор??? А разве с функцией такое не может никак получится???

Это сообщение отредактировал(а) C/L - 25.2.2009, 10:36
PM MAIL WWW ICQ   Вверх
mes
Дата 25.2.2009, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(C/L @  25.2.2009,  09:25 Найти цитируемый пост)
Значит вместо функции надо писать конструктор??? А разве с функцией такое не может никак получится???

поможет умный указатель,  или функтор вместо функции.


Это сообщение отредактировал(а) mes - 25.2.2009, 11:26


--------------------
PM MAIL WWW   Вверх
C/L
Дата 25.2.2009, 11:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Кажется до меня дошло: чтобы объект сам уничтожился он должен быть в стеке а не в куче. И создать его в таком случае может только конструктор без оператора new. А у каждой функции свой кусок стека для локальных переменных, поэтому вернуть адрес такого объекта нельзя как и ссылку на него вернуть тоже нельзя.
PM MAIL WWW ICQ   Вверх
mes
Дата 25.2.2009, 11:32 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(C/L @  25.2.2009,  10:28 Найти цитируемый пост)
А у каждой функции свой кусок стека для локальных переменных, поэтому вернуть адрес такого объекта нельзя как и ссылку на него вернуть тоже нельзя. 

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


--------------------
PM MAIL WWW   Вверх
C/L
Дата 25.2.2009, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 31.7.2004
Где: Самара

Репутация: нет
Всего: 1



Цитата(mes @  25.2.2009,  13:25 Найти цитируемый пост)
поможет умный указатель,  или функтор вместо функции.

Спасибо за помощь. Буду юзать умные указатели!
PM MAIL WWW ICQ   Вверх
bsa
Дата 25.2.2009, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196




M
bsa
если ответ на вопрос получен, то пометь тему решенной

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0567 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.