Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
1

Конструкторы и механизм return

04.04.2014, 15:05. Показов 1731. Ответов 19
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
using namespace std;
 
struct M
{
    M() { cout << "1\n"; }
    M(const M&) { cout << "2\n"; }
    M& operator=(const M&) { cout << "3\n"; return *this; }
    ~M() { cout << "4\n"; }
    int a[10000];
};
 
M func()
{
    M x;
    return x; 
}
 
int main()
{
     M y = func();
}
Почему выводится 1 4? MSVS 2012
По логике, должен вызваться конструктор объекта x, этот объект вернет свою копию. Затем будет вызван копирующий конструктор объекта y. Будет вызван деструктор для x, потом для y. Может компилятор так соптимизил...

Добавлено через 19 минут
gcc тоже самое выводит
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.04.2014, 15:05
Ответы с готовыми решениями:

В чем разница между return и return false/true
Привет всем. Вот подскажите плиз) return; return false; return true; расскажите пожалуйста...

Как сделать так, что если файл существует return true, если нет - return false
Здравствуйте, я новичок в программировании. Мой вопрос очень прост: как сделать так, что если файл...

Что это isOk(int s),setAge(int g){if(isOk(g){age=g;return true;}else{.;return false;}}.getName(){return name;}?
package com.company; import java.io.Serializable; public class person implements Serializable {...

Webpack собирает проект, а приложение говорит что мои конструкторы не конструкторы
Помогите пожалуйста, в едином файле (не билде) всё работает хорошо, как только начинаю отделять...

19
zzzZZZ...
527 / 358 / 94
Регистрация: 11.09.2013
Сообщений: 2,041
04.04.2014, 15:07 2
в функции вызывается конструктор по-умолчанию, вы создаете y и присваеваете ему объект с конструктором по-умолчанию - отсюда 1, потом деструктор - 4
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:12 3
Цитата Сообщение от Dani Посмотреть сообщение
Может компилятор так соптимизил...
Да.

Добавлено через 4 минуты
Цитата Сообщение от dzrkot Посмотреть сообщение
вы создаете y и присваеваете ему объект с конструктором по-умолчанию - отсюда 1
1 из
Цитата Сообщение от dzrkot Посмотреть сообщение
в функции вызывается конструктор по-умолчанию
По поводу
Цитата Сообщение от dzrkot Посмотреть сообщение
потом деструктор - 4
Нет, потом конструктор копирования по возвращению из функции, а потом уже деструктор.
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:13  [ТС] 4
если уж
Цитата Сообщение от dzrkot Посмотреть сообщение
присваеваете
то должен был бы вызваться operator=
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:14 5
Цитата Сообщение от Dani Посмотреть сообщение
gcc тоже самое выводит
Собери без оптимизации.
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:14  [ТС] 6
Сейчас попробую
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:14 7
Цитата Сообщение от Vourhey Посмотреть сообщение
а потом уже деструктор.
имею ввиду деструктор для x. Само собой, потом деструктор для y.
0
Эксперт по математике/физикеЭксперт С++
2048 / 1366 / 395
Регистрация: 16.05.2013
Сообщений: 3,506
Записей в блоге: 6
04.04.2014, 15:17 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
#include <iostream>
using namespace std;
struct M
{
    M() { cout << "1\n"; }
    M(const M&) { cout << "2\n"; }
    M& operator=(const M&) { cout << "3\n"; return *this; }
    ~M() { cout << "4\n"; };
    M& operator+(int t) {
        r += t;
        return *this;
    }
    int r;
};
M func()
{
    M x;
    return x + 1;
}
 
int main()
{
    M y = func();
    return 0;
}
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:19  [ТС] 9
Цитата Сообщение от Vourhey Посмотреть сообщение
Собери без оптимизации.
А как в gcc отключить оптимизации? Вроде бы без -O2 и всяких свистелок компилю.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
04.04.2014, 15:19 10
Оптимизация бывает разная. Тут в частности срабатывает вот это:
http://stackoverflow.com/quest... tudio-2010
Еще для поиска: no-elide-constructors
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:24  [ТС] 11
В студии отключил отпимизации, получилось 1 2 4 4

Добавлено через 2 минуты
А как вообще можно заставить компилятор не оптимизировать здесь? Т.е. есть проект, включена оптимизация, но в таких местах, допустим, критически важен вызов копирующего конструктора, как заставить компилятор здесь не оптимизировать?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:25 12
Цитата Сообщение от Dani Посмотреть сообщение
А как вообще можно заставить компилятор не оптимизировать здесь?
У тебя в программе нет места, где был бы важен вызов копирующего конструктора, поэтому компилятор оптимизирует.
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:30  [ТС] 13
Vourhey, даже если я сделаю так M(const M&) { a[1] = 14; cout << "2\n"; }, все равно 1 4. Хотя тут идет важная часть (присвоение 14). Или что имеется ввиду под выражением "важная часть"?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
04.04.2014, 15:41 14
Цитата Сообщение от Dani Посмотреть сообщение
А как вообще можно заставить компилятор не оптимизировать здесь?
По ссылке, что я привел, написано, что для студии никак. Для gcc -fno-elide-constructors
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:47  [ТС] 15
Только что запустил для gcc: получилось 1 2 4 2 4 4. То есть: в func() запускается конструктор объекта x, x копируется копирующим конструктором во временной объект, затем x удаляется, запускается копирующий конструктор для y, который копирует значения из временного объекта, затем временный объект удаляется, потом удаляется y. Правильно?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:54 16
Цитата Сообщение от Dani Посмотреть сообщение
Или что имеется ввиду под выражением "важная часть"?
C++
1
2
3
4
5
M func()
{
    M x;
    return x; 
}
Это создание объекта по умолчанию, и используется объект только внутри функции. То есть, он не важен ни в одно части программы. Поэтому при оптимизации твоего кода x можно вообще убирать и работать с одним y.
Думаю, что если добавить static перед M x;, то оптимизатор не станет убирать x Это не решение, это просто пример, почему оптимизатор убирает x.
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 16:01  [ТС] 17
Поставил static. Скомпилил в gcc без опций: вывод 1 2 4 4. Скомпилил в gcc с -fno-elide-constructors, получилось 1 2 2 4 4 4. Куда делать еще одна двойка и четверка при компиляции без опций? Обходимся без временного объекта? Как тогда это происходит?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 16:07 18
Цитата Сообщение от Dani Посмотреть сообщение
Обходимся без временного объекта? Как тогда это происходит?
Просто. Например:
C++
1
2
3
4
5
6
7
8
M func()
{
    M x;
    x.a[1] =10;
    return x; 
}
 
M y =  func();
Спокойно может быть сокращено до, грубо:
C++
1
2
M y;
y.a[1] = 10;
с точки зрения результата - идентично.
1
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 16:13  [ТС] 19
Вот нашел здесь такое: http://rsdn.org/forum/cpp/1436516.all
А>1.

C++
1
2
3
4
5
6
int f(){
  int y = 5;
  return 5;
}
 
a  = f(); //вот тут вычислится значение f - выделится память на int и после присвоения - освободится

большинство реализаций скомпилируют это так, что f вернёт значение в каком-нибудь предназначенном для этого месте проца, например в специальном регистра. На Intel это обычно eax. оттуда это значение и будет сохранено в переменную a.


А>2.


C++
1
2
3
4
5
const char* f(){
 return "qwe";
}
 
const char *str = f(); // Что вот тут будет? Какая память выделяется и что с ней дальше происходит?

Строчка "qwe" выделится в сегменте статических данных и будет там спокойно жить, когда функция затеет его возвращать, она вернёт просто сам указатель, то есть тоже как атомарное значение, то есть всё будет очень похоже на п 1, только значение будет передаваться другое. Оно же и сохранится в str.
Правда есть одно замечание. В C++ "qwe" имет тип const char [4], так что чтобы всё было по стандарту, нужно писать ещё и выделенное полужирным const

А>3.


C++
1
2
3
4
5
6
char* f(){
 char qw[] = "qwe";
 return qw;
}
 
char *str = f(); // Что вот тут будет? Какая память выделяется и что с ней дальше происходит?

А вот тут будет плохо!

char qw[] = "qwe"; -- это объявление автоматического массива из 4-х char'ов, и инициализация его кодами букв q, w, e и 0.
После чего адрес этого массива (то есть адрес данных на стеке), будет возвращён из функции так же как был возвращён адрес во втором случае. Но, так как стековый фрейм f будет к этому моменту разрушен, то эти данные довольно скоро будет затёрты какими-нибудь другими пользователями стека, так что вы получити какой-то мусор.

Но есть ещё и
4

C++
1
2
3
4
5
6
7
8
9
10
11
12
struct IntData {
   int Size;
   int Data[15];
};
 
IntData f() {
   IntData result;
   //  тут как-то инициализируют поля переменной result
   return result;
}
 
IntData data = f(); // Что вот тут будет? Какая память выделяется и что с ней дальше происходит?

Произойдёт интересно.
Так как структура IntData довольно большая, то она уже скорее всего не сможет быть передана через "волшебное место" в процессоре, так что она будет передаваться через память. Обычно это происходит так:
1) Тот кто вызывает, заводит у себя место под возвращаемое значние функции. Если компилятор не совсем того, то в данном контексте это будет непосредственно место под переменную data.
2) у функции f() на самом деле есть тайный параметр, куда передаётся указатель на это место
3) в операторе return будет вызван конструктор IntData, при этом объект будет сконструирован как раз в том самом месте. В этом варинте функции позовут конструктор копирования.
4) Вызывающая сторона сама решает как распорядиться полученным временным объектом. В жанном варианте (если компилятор не совсем того), то временного объекта вообще не будет и мы просто получим инициализированную переменную data и программа продолжит выполнение.

Сообщение довольно старое. Этому можно верить? Сейчас тоже так все происходит?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 16:18 20
Цитата Сообщение от Dani Посмотреть сообщение
Сообщение довольно старое. Этому можно верить? Сейчас тоже так все происходит?
Да.
То, что я написал про
Цитата Сообщение от Vourhey Посмотреть сообщение
M y;
y.a[1] = 10;
Если вдаваться в детали, то вызов func все равно может быть в наличии. Но работать он будет с объектом постоянным, а не временным. Но для простоты я написал так, чтобы объяснить, почему не будет конструктора копирования
1
04.04.2014, 16:18
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.04.2014, 16:18
Помогаю со студенческими работами здесь

Что такое в jquery и java return false и return true
Если я правильно понимаю, то return false отменяет действие по умолчанию, например клик по ссылке,...

Односвязный список - объясните, как работают return 0 и return 1
проверьте, пжлса, по комментариям правильно ли я поняла принцип работы программы. Объясните, как...

saeco royal classic заварной механизм дергается рывками, машина останавливается с ошибкой, в тестовом режиме заварной механизм двигается нормально, в рабочем - н
Добр. день. Предыстория - заварной механизм говорят заклинило что-ли.... Отнесли в сервис - там...

How can to return value (return value; ) of javascript function to ASP ?
How can to return value (return value; ) of javascript function to ASP ?


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru