Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: [c++] оператор return  (Прочитано 11432 раз)
0 Пользователей и 1 Гость смотрят эту тему.
The Nameless One
Помогающий

ru
Offline Offline
Пол: Мужской

« : 10-08-2009 17:34 » 

Нужна помощь, чтобы понять ещё некоторые тонкости.

Когда функция возвращает некий объект, то перед этим создаётся копия этого объекта, затем эта копия уничтожается (вызывается деструктор).
1. Зачем так сделано?
2. В какой момент уничтожается эта копия, сразу после присваивания?

Например, есть некий класс A. И функция возращает объект этого класса.
Код:
A func1()
{
    A temp;   //создаётся temp в стеке.
    ...
                    
    return temp;
                  //создаётся копия temp в стеке.
                  //уничтожается temp.
                  //а когда уничтожается копия temp?
}  

А если функция возвращает ссылку на некую глобальную переменную или член класса, в этом случае не создается никаких лишних копий?
Код:
double dX;
double& Getdx() {return dX;}

А если не ссылку, а сам объект:
Код:
double GetdX() {return dx;}
, то создается копия dX, которая возвращается?
Код:
double dY=GetdX();
- здесь в какой момент временная копия dX внутри функции уничтожится? После присваивания dY?
« Последнее редактирование: 10-08-2009 17:40 от The Nameless One » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 10-08-2009 18:03 » 

Если ты внутри функции иницилизировал статически экземпляр класса, то сразу после завершаюшей скобки и выхода из зоны видимости функции, класс будет автоматически уничтожен. С вызовом его деструктора.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 10-08-2009 18:04 » 

Копия temp уничтожается, как любая другая временная переменная, после вычисления выражения, в котором она участвует.
Код:
A val = func1();
- здесь копирующий конструктор, создающий val, получит в качестве аргумента временную переменную (в общем случае, копию temp). Эта переменная будет уничтожена сразу после выполнения конструктора.
Можно ещё взять такие примеры:
Код:
void foo(A param){
    // ...
}

void foo2(A& param){
    //...
}

A func1(){
    return A();
}

int main() {
    A temp = func1();
    foo(func1());
    foo2(func1());
}
можешь добавить отладочный вывод и посмотреть, что будет Ага

Есть одна тонкость: компилятор может оптимизировать создание временных объектов: если у тебя уже есть временная temp на стеке, то вторая может не создаваться. Скажем, есть такой код:
Код:
class Test
{
public:
Test(){}
const Test& operator=(const Test& val){ return *this; }
Test(const Test& val){}
~Test(){}
};

Test foo()
{
Test test;
return test;
}

int main()
{
Test val;
val = foo();
return 0;
}
то в результате сначала создаётся Test val, затем вызывается функция и создаётся временный объект test, а на выходе из функции происходит вызов оператора копирования из этого временного объекта в val. Итого, на стеке создаётся только 2 объекта.

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

Если возвращать значение - то будет копироваться значение (с поправкой на оптимизацию, которую может применить компилятор).
« Последнее редактирование: 10-08-2009 18:39 от Вад » Записан
The Nameless One
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 10-08-2009 18:34 » 

Большое спасибо за подробные разъяснения:)
Записан
Mayor
Специалист

ru
Offline Offline

« Ответ #4 : 11-08-2009 16:07 » 

Когда функция возвращает некий объект, то перед этим создаётся копия этого объекта, затем эта копия уничтожается (вызывается деструктор).
1. Зачем так сделано?
2. В какой момент уничтожается эта копия, сразу после присваивания?

Например, есть некий класс A. И функция возращает объект этого класса.
Код:
A func1()
{
    A temp;   //создаётся temp в стеке.
    ...
                    
    return temp;
                  //создаётся копия temp в стеке.
                  //уничтожается temp.
                  //а когда уничтожается копия temp?
}  

че то я не догоняю почему ты решил, что return создает новый объект
в стандарте вроде сказано что объект создается при объявлении:
A temp;
если тебе охото в return создать новый объект, то нужно там его и объявлять:
return A();
Записан

1n c0de we trust
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 11-08-2009 21:07 » 

Mayor, а какже тогда быть с } ? Ведь temp, как локальная переменная, прекратит своё существование в этом месте. Что ж тогда возвращать?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 12-08-2009 03:53 » 

Переформулирую вопрос Джона Улыбаюсь
Если есть код
Код:
ClassA foo(params){
    if (some_condition(params)){
        ClassA temp1;
        // do smth
        return temp1;
    }
    else if (some_other_condition(params)){
        // do smth
        return ClassA(/*...*/);
    }
    int someval;
    ClassA temp2;
    // do smth
    return temp2;
}
то, в общем случае, какой именно объект будет тем, который будет лежать на стеке после выхода из функции? Особенно в последнем случае, когда выше по стеку от temp2 располагается int?
Ещё раз: компилятор может упростить и соптимизировать, но не все случаи хорошо оптимизируются.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #7 : 12-08-2009 03:57 » 

Mayor, как известно, передача параметра по значению, так же, как и возврат результата по значению приводят к созданию временного объекта, конечно с некоторыми исключениями.
О чем коллеги уже сообщили Улыбаюсь и даже рассказали почему
Записан

Странно всё это....
Mayor
Специалист

ru
Offline Offline

« Ответ #8 : 12-08-2009 16:05 » 

Mayor, как известно, передача параметра по значению, так же, как и возврат результата по значению приводят к созданию временного объекта, конечно с некоторыми исключениями.
О чем коллеги уже сообщили Улыбаюсь и даже рассказали почему

капец стандартик, я то думал оператор= вызывается еще до разрушения стека foo()
test t1;
t1=foo();
а оказалось, что нет: поэтому вызов оператора копирования остается на усмотрении компилятора:
Код:
test t2;
t2=f1();

test f1(void){
int i=0;
cin>>i;
if (i==1) {
test t;
return t;
}
test t1;
return t1; //вызовет
}
test f1(void){
/* int i=0;
cin>>i;
if (i==1) {
test t;
return t;
} */
test t1;
return t1; // не вызовет
}

вот и пиши после этого конструкторы с потусторонними эффектами
Записан

1n c0de we trust
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines