Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
mamucho666
1 / 1 / 0
Регистрация: 06.06.2012
Сообщений: 13
16.07.2012, 17:07     Удаляется объект когда не требуется и всё равно продолжает существовать #1
Всем привет. Честно говоря я не знаю как ещё более правильно описать проблему в заголовке. В общем проходил раздел, посвящённый <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. Заранее благодарен.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.07.2012, 17:07     Удаляется объект когда не требуется и всё равно продолжает существовать
Посмотрите здесь:

окно всё равно закрывается.... C++
сегодня наконец то понял что такое КЛАСС, и ОБЪЕКТ. понято всё, кроме одного - зачем всё это? в смысле, можно же без этого? так зачем жизнь усложнять? C++
this это адресс объекта, а *this это сам объект. я всё правельно понял? C++
C++ Конструктор, принимающий в качестве аргумента ссылку на объект, всё портит
Созданный объект Array<char> удаляется, как только метод convert завершается C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.07.2012, 17:10     Удаляется объект когда не требуется и всё равно продолжает существовать #2
C++
1
ok2 a(ok1(100));
Вы создаете объект ok2 передавая ссылку на временный объект, после передачи ссылки, объект удаляется, это UB если я не ошибаюсь.
mamucho666
1 / 1 / 0
Регистрация: 06.06.2012
Сообщений: 13
16.07.2012, 17:32  [ТС]     Удаляется объект когда не требуется и всё равно продолжает существовать #3
То есть аргументы удаляются так же как и параметры? Не знал, хотя догадывался. Но это можно принять. Остаётся вопрос - почему я всё равно могу пользоваться объектом?
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 17:49     Удаляется объект когда не требуется и всё равно продолжает существовать #4
mamucho666, это вообще компилируется? В конструктор вы передаете временный объект, хотя он должен принимать ссылку.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.07.2012, 17:52     Удаляется объект когда не требуется и всё равно продолжает существовать #5
mamucho666, Всмысле удаляются так же как параметры? Что происходит в вашем коде.
1) Вызывается конструктор ok1.
2) Вызывается конструктор ok2 и передается ссылка на ранее созданный ok1.
3) Так как объект ok1 временный - вызывается деструктор ok1.

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

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

А можно как-то посмотреть во что он превратил код? То есть посмотреть какую-то информацию о том что сейчас в программе происходит? Что создаётся, что удаляется и тд и тп.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
16.07.2012, 18:30     Удаляется объект когда не требуется и всё равно продолжает существовать #10
О как. В 2012 RC студии оно тоже работает и дает тот же вывод что у ТС.
DU
1477 / 1053 / 45
Регистрация: 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
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 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 запихивает.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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, твой код откомпилировался.
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:42     Удаляется объект когда не требуется и всё равно продолжает существовать #14
Цитата Сообщение от ForEveR Посмотреть сообщение
А вот так он дает то что нужно, сдается мне что он вместо ссылки поставляет rvalue-ссылку или const-ссылку.
Хм. Тогда, ТС, попробуйте изменить refobj в конструкторе.

Добавлено через 2 минуты
Хотя все равно не понятно, как он const & будет преобразовывать в &, поскольку не известно, что находится pз const &. Если все пройдет гладко - налицо нарушение стандарта. На это указывает, кстати, и вывод DU
Цитата Сообщение от DU Посмотреть сообщение
nonstandard extension
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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.
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:44     Удаляется объект когда не требуется и всё равно продолжает существовать #16
ForEveR, я поэтому и просил, чтобы компилил именно ТС. MSVC12, ведь, уже обзавелась rvalue-reference? Так вот, если в конструкторе & изменить на &&, то вывод на g++ 4.7.1 будет тоже 5
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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 насколько я помню.
soon
 Аватар для soon
2536 / 1301 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
16.07.2012, 18:56     Удаляется объект когда не требуется и всё равно продолжает существовать #18
Цитата Сообщение от ForEveR Посмотреть сообщение
К слову 10-ка тоже была с rvalue-ref насколько я помню.
Похоже, да, wiki тоже об этом говорит.
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;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.07.2012, 19:05     Удаляется объект когда не требуется и всё равно продолжает существовать
Еще ссылки по теме:

C++ Почему удаляется объект?
C++ Объект удаляется до возвращения его из функции
C++ Зачем нужно освобождать память динамических объектов в деструкторе, если всё равно это сделает менеджер памяти

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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, а не то что вы хотели.
Yandex
Объявления
16.07.2012, 19:05     Удаляется объект когда не требуется и всё равно продолжает существовать
Ответ Создать тему
Опции темы

Текущее время: 21:34. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru