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

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

16.07.2012, 17:07. Просмотров 1210. Ответов 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
Ответы с готовыми решениями:

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

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

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

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

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

24
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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
В астрале
Эксперт С++
7995 / 4754 / 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...

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


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

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

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