Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
mamucho666
1 / 1 / 0
Регистрация: 06.06.2012
Сообщений: 13
#1

Удаляется объект когда не требуется и всё равно продолжает существовать - C++

16.07.2012, 17:07. Просмотров 1201. Ответов 24
Метки нет (Все метки)

Всем привет. Честно говоря я не знаю как ещё более правильно описать проблему в заголовке. В общем проходил раздел, посвящённый <functional>, и, собственно, там всё понятно, но заметил одну странность, потом перепроверил в специально написанном для проверки более простом коде и она подтвердилась.
Код ниже выводит на экран вот эти надписи:

ok1
ok2
delete ok1
100

delete ok2

Вопросы мои по поводу выделенных жирным.

1. Зачем удаляется объект класса ок1 до завершения функции в которой он создан?
2. Если он удалился, то откуда тогда взялся доступ к члену этого объекта?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct ok1
{
    ok1(int i):val(i){cout << "ok1" << endl;}
    int val;
    ~ok1(){cout << "delete ok1" << endl;}
};
struct ok2
{
    ok2 (ok1 & refobj):obj(refobj){cout << "ok2" << endl;}
    ok1 & obj;
    ~ok2(){cout << "delete ok2" << endl;}
};
int main()
{
    ok2 a(ok1(100));
    cout << a.obj.val << endl;
    system("pause");
    return 0;
}
P.S. Заранее благодарен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.07.2012, 17:07
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Удаляется объект когда не требуется и всё равно продолжает существовать (C++):

Как опять начать всё заного, когда всё окончилось
// тут есть массивы с вопросами и ответами... int main() { ...

сегодня наконец то понял что такое КЛАСС, и ОБЪЕКТ. понято всё, кроме одного - зачем всё это? в смысле, можно же без этого? так зачем жизнь усложнять?
сегодня наконец то понял что такое КЛАСС, и ОБЪЕКТ. понято всё, кроме одного -...

окно всё равно закрывается....
Всем доброго времени суток! прочитал тему тут понял что в конце программы...

Почему удаляется объект?
Помогите, пожалуйста, понять почему удаляется объект и как это исправить? Идея...

Объект удаляется до возвращения его из функции
Есть следующий код перегрузки операции &quot;+&quot; для сложения матриц: Matrix...

удаляется ли объект или происходит утечка памяти?
Добрый день, подскажите, при таком коде, удаляется ли объект или происходит...

24
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 17:10 #2
C++
1
ok2 a(ok1(100));
Вы создаете объект ok2 передавая ссылку на временный объект, после передачи ссылки, объект удаляется, это UB если я не ошибаюсь.
0
mamucho666
1 / 1 / 0
Регистрация: 06.06.2012
Сообщений: 13
16.07.2012, 17:32  [ТС] #3
То есть аргументы удаляются так же как и параметры? Не знал, хотя догадывался. Но это можно принять. Остаётся вопрос - почему я всё равно могу пользоваться объектом?
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 17:49 #4
mamucho666, это вообще компилируется? В конструктор вы передаете временный объект, хотя он должен принимать ссылку.
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 17:52 #5
mamucho666, Всмысле удаляются так же как параметры? Что происходит в вашем коде.
1) Вызывается конструктор ok1.
2) Вызывается конструктор ok2 и передается ссылка на ранее созданный ok1.
3) Так как объект ok1 временный - вызывается деструктор ok1.

Следовательно ok2 уже не должен обращаться к этим данным, т.к. иначе это undefined behaviour.
И кстати внятный компилятор скажет об этом, пример - http://liveworkspace.org/code/ceaf31b62675541c8cdb8d05f3208eb3
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:15 #6
ИМХО, никакого UB тут нет. Временный объект - rvalue. Ссылочный объект - lvalue. Как ТС хочет, чтобы rvalue преобразовалось в lvalue?
1
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 18:18 #7
soon, На самом деле да, я ступил, но вопрос почему у ТС это компилируется, ведь раз он показывает вывод - значит он смог это запустить.
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:23 #8
ForEveR, я вначале даже подумал, что ТС переписывал код на форум вручную и вместо rvalue reference написал просто reference. В таком случае, вывод действительно будет как у ТС.
0
mamucho666
1 / 1 / 0
Регистрация: 06.06.2012
Сообщений: 13
16.07.2012, 18:28  [ТС] #9
Компилятор майкрософтовский, 2010. И да, soon прав.

Наверно компилятор как-то сам исправил, но он даже предупреждения не выдаёт(

А можно как-то посмотреть во что он превратил код? То есть посмотреть какую-то информацию о том что сейчас в программе происходит? Что создаётся, что удаляется и тд и тп.
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 18:30 #10
О как. В 2012 RC студии оно тоже работает и дает тот же вывод что у ТС.
0
DU
1486 / 1132 / 164
Регистрация: 05.12.2011
Сообщений: 2,279
16.07.2012, 18:33 #11
поставте уровень ворнингов проекта на максимум. вот что 2008 студия выдает:
warning C4239: nonstandard extension used : 'argument' : conversion from 'Obj' to 'Obj &' A non-const reference may only be bound to an lvalue
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:36 #12
Но это же бред. Временный объект может кастоваться разве что в const & и &&. ТС, ForEveR, попробуйте скомпилить это
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
#include <iostream>
 
using namespace std;
 
struct ok1
{
    ok1(int i):val(i){cout << "ok1" << endl;}
    int val;
    ~ok1(){cout << "delete ok1" << endl;}
};
struct ok2
{
    ok2 (ok1 & refobj):obj(refobj){cout << "ok2" << endl;}
    ok1 & obj;
 
    void setOk1(const ok1& k)
    {
        obj = k
    }
 
    ~ok2(){cout << "delete ok2" << endl;}
};
int main()
{
    ok2 a(ok1(100));
    cout << a.obj.val << endl;
    ok1 k(1);
    a.setOk1(k);
    // system("pause");
    return 0;
}
Может он ссылку в const запихивает.
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 18:36 #13
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
#include <iostream>
 
using std::cout;
using std::endl;
 
struct ok1
{
    ok1(int i):val(i){cout << "ok1" << endl;}
    int val;
    ~ok1(){cout << "delete ok1" << endl;}
};
struct ok2
{
    ok2 (volatile ok1 & refobj):obj(const_cast<ok1&>(refobj)){cout << "ok2" << endl;}
    ok1 & obj;
    ~ok2(){cout << "delete ok2" << endl;}
};
int main()
{
    ok2 a(ok1(100));
    cout << a.obj.val << endl;
    system("pause");
    return 0;
}
Ошибка 1 error C2664: ok2::ok2(volatile ok1 &): невозможно преобразовать параметр 1 из "ok1" в "volatile ok1 &" c:\users\forever\documents\visual studio 11\projects\consoleapplication1\consoleapplication1\create.cpp 20 1 ConsoleApplication1

А вот так он дает то что нужно, сдается мне что он вместо ссылки поставляет rvalue-ссылку или const-ссылку.

soon, твой код откомпилировался.
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:42 #14
Цитата Сообщение от ForEveR Посмотреть сообщение
А вот так он дает то что нужно, сдается мне что он вместо ссылки поставляет rvalue-ссылку или const-ссылку.
Хм. Тогда, ТС, попробуйте изменить refobj в конструкторе.

Добавлено через 2 минуты
Хотя все равно не понятно, как он const & будет преобразовывать в &, поскольку не известно, что находится pз const &. Если все пройдет гладко - налицо нарушение стандарта. На это указывает, кстати, и вывод DU
Цитата Сообщение от DU Посмотреть сообщение
nonstandard extension
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 18:42 #15
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 ok1
{
    ok1(int i):val(i){cout << "ok1" << endl;}
    int val;
    ~ok1(){cout << "delete ok1" << endl;}
};
 
struct ok2
{
    ok2 (ok1 & refobj):obj(refobj){cout << "ok2" << endl; refobj.val = 5;}
    ok1 & obj;
 
    ~ok2(){cout << "delete ok2" << endl;}
};
 
int main()
{
    ok2 a(ok1(100));
    cout << a.obj.val << endl;
    return 0;
}
Вывод 5.
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:44 #16
ForEveR, я поэтому и просил, чтобы компилил именно ТС. MSVC12, ведь, уже обзавелась rvalue-reference? Так вот, если в конструкторе & изменить на &&, то вывод на g++ 4.7.1 будет тоже 5
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 18:45 #17
Да-с, нарушение стандарта. 1>c:\users\forever\documents\visual studio 11\projects\consoleapplication1\consoleapplication1\create.cpp(22): warning C4239: нестандартное расширение: аргумент: преобразование "ok1" в "ok1 &"
К слову 10-ка тоже была с rvalue-ref насколько я помню.
0
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:56 #18
Цитата Сообщение от ForEveR Посмотреть сообщение
К слову 10-ка тоже была с rvalue-ref насколько я помню.
Похоже, да, wiki тоже об этом говорит.
0
mamucho666
1 / 1 / 0
Регистрация: 06.06.2012
Сообщений: 13
16.07.2012, 19:01  [ТС] #19
Вы меня просите о чём я понятия не имею. Что значит изменить refobj?
Если вы не против, скиньте мне просто готовый код, который надо скомпилить.

У меня пока вопрос возник, почему в коде ok(a) выдаёт ошибку, при чём вообще непонятную
(
(11): error C2371: a: переопределение; различные базовые типы
(10): см. объявление "a"
(11): error C2512: ok: нет подходящего конструктора по умолчанию),
)
а создание именованного объекта ok b(a) проходит успешно?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct ok
{
    ok(int i):val(i){cout << "ok" << endl;}
    int val;
    ~ok(){cout << "delete ok" << endl;}
};
int main()
{
    int a(100);
    ok(a);
    ok b(a);
    system("pause");
    return 0;
}
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
16.07.2012, 19:05 #20
soon, Даже стало интересно, как-то вообще можно проверить каким образом компилятор делает такое корректным? По сути тест case какой-то такой

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
 
using namespace std;
 
void value(string& value)
{
}
 
int main()
{
    value(string());
}
Кстати, для примитивных типов, это не работает (int etc.).

Добавлено через 53 секунды
C++
1
ok(a);
Объявление объекта a типа ok, а не то что вы хотели.
0
16.07.2012, 19:05
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.07.2012, 19:05
Привет! Вот еще темы с решениями:

Созданный объект Array<char> удаляется, как только метод convert завершается
Есть простенькая оболочка над массивом Array&lt;T&gt;: template&lt;typename T&gt; class...

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

Зачем нужно освобождать память динамических объектов в деструкторе, если всё равно это сделает менеджер памяти
Не скажу за все ОС-и, но под Windows есть менеджер памяти. Когда по ходу кода...

Почему процесс продолжает существовать после закрытия окна?
1. К MS Access 2000 подключил COM Add-in написанный на VBA. При соединении...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru