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

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

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

Студворк — интернет-сервис помощи студентам
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
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.04.2014, 15:05
Ответы с готовыми решениями:

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

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

Что это 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 { protected String name; ...

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

Добавлено через 4 минуты
Цитата Сообщение от dzrkot Посмотреть сообщение
вы создаете y и присваеваете ему объект с конструктором по-умолчанию - отсюда 1
1 из
Цитата Сообщение от dzrkot Посмотреть сообщение
в функции вызывается конструктор по-умолчанию
По поводу
Цитата Сообщение от dzrkot Посмотреть сообщение
потом деструктор - 4
Нет, потом конструктор копирования по возвращению из функции, а потом уже деструктор.
1
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:13  [ТС]
если уж
Цитата Сообщение от dzrkot Посмотреть сообщение
присваеваете
то должен был бы вызваться operator=
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:14
Цитата Сообщение от Dani Посмотреть сообщение
gcc тоже самое выводит
Собери без оптимизации.
0
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:14  [ТС]
Сейчас попробую
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:14
Цитата Сообщение от Vourhey Посмотреть сообщение
а потом уже деструктор.
имею ввиду деструктор для x. Само собой, потом деструктор для y.
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2224 / 1426 / 420
Регистрация: 16.05.2013
Сообщений: 3,646
Записей в блоге: 6
04.04.2014, 15:17
Скорее всего оптимизация. Если немного попытаться обмануть компилятор то все получится как положенно:
Кликните здесь для просмотра всего текста

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
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:19  [ТС]
Цитата Сообщение от Vourhey Посмотреть сообщение
Собери без оптимизации.
А как в gcc отключить оптимизации? Вроде бы без -O2 и всяких свистелок компилю.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
04.04.2014, 15:19
Оптимизация бывает разная. Тут в частности срабатывает вот это:
http://stackoverflow.com/quest... tudio-2010
Еще для поиска: no-elide-constructors
1
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:24  [ТС]
В студии отключил отпимизации, получилось 1 2 4 4

Добавлено через 2 минуты
А как вообще можно заставить компилятор не оптимизировать здесь? Т.е. есть проект, включена оптимизация, но в таких местах, допустим, критически важен вызов копирующего конструктора, как заставить компилятор здесь не оптимизировать?
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
04.04.2014, 15:25
Цитата Сообщение от Dani Посмотреть сообщение
А как вообще можно заставить компилятор не оптимизировать здесь?
У тебя в программе нет места, где был бы важен вызов копирующего конструктора, поэтому компилятор оптимизирует.
0
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:30  [ТС]
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
Цитата Сообщение от Dani Посмотреть сообщение
А как вообще можно заставить компилятор не оптимизировать здесь?
По ссылке, что я привел, написано, что для студии никак. Для gcc -fno-elide-constructors
1
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 15:47  [ТС]
Только что запустил для 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
Цитата Сообщение от Dani Посмотреть сообщение
Или что имеется ввиду под выражением "важная часть"?
C++
1
2
3
4
5
M func()
{
    M x;
    return x; 
}
Это создание объекта по умолчанию, и используется объект только внутри функции. То есть, он не важен ни в одно части программы. Поэтому при оптимизации твоего кода x можно вообще убирать и работать с одним y.
Думаю, что если добавить static перед M x;, то оптимизатор не станет убирать x Это не решение, это просто пример, почему оптимизатор убирает x.
1
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 16:01  [ТС]
Поставил 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
Цитата Сообщение от 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
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.04.2014, 16:13  [ТС]
Вот нашел здесь такое: 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
Цитата Сообщение от Dani Посмотреть сообщение
Сообщение довольно старое. Этому можно верить? Сейчас тоже так все происходит?
Да.
То, что я написал про
Цитата Сообщение от Vourhey Посмотреть сообщение
M y;
y.a[1] = 10;
Если вдаваться в детали, то вызов func все равно может быть в наличии. Но работать он будет с объектом постоянным, а не временным. Но для простоты я написал так, чтобы объяснить, почему не будет конструктора копирования
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.04.2014, 16:18
Помогаю со студенческими работами здесь

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

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

Односвязный список - объясните, как работают return 0 и return 1
проверьте, пжлса, по комментариям правильно ли я поняла принцип работы программы. Объясните, как здесь работают 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
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru