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

Реализация собственного умного укзателя - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.65
Philosophistic
0 / 0 / 0
Регистрация: 20.10.2011
Сообщений: 9
25.08.2012, 10:18     Реализация собственного умного укзателя #1
Доброго времени суток!

При самостоятельной реализации умного указателя столкнулся с проблемой при удалении самого указателя.

Код программы имеет вид:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#pragma once
template <class Object>
class Smart_ptr
{
public:
    Smart_ptr<Object>( Object *ptr = new Object )
    {
        this->ptr = ptr;
    }
    Smart_ptr<Object>( const Smart_ptr<Object> &obj )
    {   
        ptr = obj.ptr;
    }
    ~Smart_ptr<Object>( void )
    {
        delete ptr;
    }
 
    bool isNull( void )
    {
    return (ptr == 0);
    }
 
    Smart_ptr<Object> &operator=( const Smart_ptr<Object> &obj )
    {
    if ( this != &obj )
    {
        delete ptr;
        ptr = obj.ptr;
    }
    return *this;
    }
    Object &operator*( void ) const
    {
        return *ptr;
    }
    Object *operator->( void ) const
    {
    return ptr;
    }
    Object &operator[]( const int index )
    {
        if ( ptr != 0 )
    {
        return ptr[ index ];
    } else
    {
        cout << endl << "Unable to get the element with index = " << index;
        exit( 0 );
    }
    }
 
private:
    Object *ptr;
};
Код прекрасно работает до двух моментов:
1) До момента вызова деструктора.
2) До момента использования оператора присваивания.

Если в обоих случаях закомментировать строку
C++
1
delete ptr
, то никаких проблем не возникает. Указатель в исходнике ссылается на структуру.

Подскажите, пожалуйста, в чем может быть проблема.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
25.08.2012, 10:38     Реализация собственного умного укзателя #2
Philosophistic, пожалуйста, поставь теги [CPP] :<

Дело в том, чтобы ты ни разу не копируешь объекты. Ты всегда гоняешь один и тот же объект по разным экземплярам, т.е :
C++
1
2
3
4
int *a = new int(10);
int *b = a;
delete a;
delete b;
В данном случае b ссылается на a. Подчистив a, у нас уже b ссылается в "ничто" и после повторной подчистке мы убиваем "ничто".
Используй strcpy (если работа со строками). Хотя, у тебя шаблон, так что лучше memcpy или CopyMemory.
Philosophistic
0 / 0 / 0
Регистрация: 20.10.2011
Сообщений: 9
25.08.2012, 11:39  [ТС]     Реализация собственного умного укзателя #3
Заменил код
C++
1
ptr = obj.ptr;
на код
C++
1
memcpy( ptr, obj.ptr, sizeof( Object ) );
И далее аналогично. Работает неверно. Что я делаю неправильно?

P.S. Все никак не могу разобраться.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
25.08.2012, 12:13     Реализация собственного умного укзателя #4
> Что я делаю неправильно?
Неправильно понимаете суть указателя со счётчиком ссылок.

Суть его в том, что при создании смарт-поинтера выделяется место под объект и под этот самый счётчик. Указатель на этот кусок памяти сохраняется в смарт-поинтере и он знает, где там лежит счётчик, а где объект.

При создании счётчик равен единице. Конструктор копирования тупо копирует в новый смартпоинтер этот указатель (и ничего не делает с объектом). То же самое делает оператор присваивания. Оба они вдобавок увеличивают на единичку счётчик (аккуратно с присваиванием самому себе, там этого делать не надо).

Деструктор счётчик уменьшает на единичку. Если счётчик стал нулём, то деструктор заодно удаляет выделенную память, на которую указывает тот указатель, что хранится во всех смарт-поинтерах на один и тот же объект.

А хорошая реализация ещё делает это быстро и является thread-safe.
Philosophistic
0 / 0 / 0
Регистрация: 20.10.2011
Сообщений: 9
27.08.2012, 00:35  [ТС]     Реализация собственного умного укзателя #5
Не работает код в конструкторе. Выдает ошибку во время работы программы.
C++
1
memcpy( this->ptr, ptr, sizeof( Object ) );
В чем причина?
softmob
1248 / 698 / 155
Регистрация: 20.02.2010
Сообщений: 1,035
27.08.2012, 01:02     Реализация собственного умного укзателя #6
класс умного указателя на подобие auto_ptr. похоже вы первоначально что то типа этого и делали
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
template <class Object>
class Smart_ptr
{
public:
    explicit Smart_ptr(Object* p = nullptr): ptr(p)
    {}
 
    Smart_ptr(Smart_ptr& a): ptr(a.ptr)
    {
        a.ptr = nulltpr;
    }
 
    ~Smart_ptr()
    {
        delete ptr;
    }
 
    Smart_ptr& operator= (Smart_ptr& a)
    {
        if (this != &a)
        {
            ptr = a.ptr;
            a.ptr = nullptr;
        }
        return *this;
    }
 
    Object &operator*() const
    {
        return *ptr;
    }
 
    Object *operator->() const
    {
        return ptr;
    }
 
    Object* get() const
    {
        return ptr;
    }
 
    Object* release()
    {
        Object* tmp(ptr);
        ptr = nullptr;
        return tmp;
    }
 
    void reset(Object* p = nullptr)
    {
        delete ptr;
        ptr = p;
    }
private:
    Object *ptr;
};
ValeryS
Модератор
6374 / 4840 / 441
Регистрация: 14.02.2011
Сообщений: 16,043
27.08.2012, 01:02     Реализация собственного умного укзателя #7
Цитата Сообщение от Philosophistic Посмотреть сообщение
this->ptr
уже куда то указывает???
может сначала память выделим?
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
27.08.2012, 01:07     Реализация собственного умного укзателя #8
Цитата Сообщение от softmob Посмотреть сообщение
Smart_ptr& operator= (Smart_ptr& a)
{
if (this != &a)
{
ptr = a.ptr;
a.ptr = nullptr;
}
return *this;
}
разве тут не должен release вызываться?:
softmob
1248 / 698 / 155
Регистрация: 20.02.2010
Сообщений: 1,035
27.08.2012, 01:14     Реализация собственного умного укзателя #9
Цитата Сообщение от alex_x_x Посмотреть сообщение
разве тут не должен release вызываться?
можно и через release
C++
1
2
3
4
5
Smart_ptr& operator= (Smart_ptr& a)
{
    ptr = a.release();
    return *this;
}
Philosophistic
0 / 0 / 0
Регистрация: 20.10.2011
Сообщений: 9
27.08.2012, 01:21  [ТС]     Реализация собственного умного укзателя #10
Цитата Сообщение от ValeryS Посмотреть сообщение
уже куда то указывает???
может сначала память выделим?
Можете мне объяснить, я ни понимаю пока полностью механизм работы с указателями. То есть мне нужно было до вызова функции написать примерно следующее?
C++
1
 this->ptr = new Object
То есть объявление в классе
C++
1
Object *ptr
объявляет указатель на объект типа Object, для которого еще нужно выделить память. Правильно ли я понял свою ошибку?
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
27.08.2012, 01:23     Реализация собственного умного укзателя #11
softmob, какбы идейно если this != &a, то нужно уменьшить счетчик ссылок
а вот если this == &a, то ничего не делать

Добавлено через 1 минуту
Цитата Сообщение от Philosophistic Посмотреть сообщение
Можете мне объяснить, я ни понимаю пока полностью механизм работы с указателями.
тогда смартпоинтеры начинать делать бессмысленно

Цитата Сообщение от Philosophistic Посмотреть сообщение
И далее аналогично. Работает неверно. Что я делаю неправильно?
зачем?
softmob
1248 / 698 / 155
Регистрация: 20.02.2010
Сообщений: 1,035
27.08.2012, 01:31     Реализация собственного умного укзателя #12
немного переделал под работу на основе счетчика пользователей
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
template <class Object>
class HasPtr
{
public:
    explicit HasPtr(Object* p = nullptr): ptr(p), use(size_t new(1))
    {}
 
    HasPtr(const HasPtr& a): ptr(a.ptr), use(a.use)
    {
        ++*use;
    }
 
    ~HasPtr()
    {
        decr_use();
    }
 
    HasPtr& operator= (const Smart_ptr& rhs)
    {
        ++*rhs.use;
        decr_use();
        ptr = rhs.ptr;
        use = rhs.use;
        return *this;
    }
 
    Object &operator*() const
    {
        return *ptr;
    }
 
    Object *operator->() const
    {
        return ptr;
    }
 
    Object* get() const
    {
        return ptr;
    }
 
    Object* release()
    {
        Object* tmp(ptr);
        ptr = nullptr;
        *use = 1;
        return tmp;
    }
 
    void reset(Object* p = nullptr)
    {
        decr_use();
        *ptr = p;
        *use = 1;
    }
private:
    void decr_use()
    {
        if (--*use == 0)
            delete ptr, delete use;
    }
    Object *ptr;
    size_t *une;
};
p.s. не пользовался умными указателями, их реализацию тоже до этого не писал. возможно что то не так...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.08.2012, 01:47     Реализация собственного умного укзателя
Еще ссылки по теме:

C++ Степенной метод нахождения наибольшего по модулю собственного значения и соответствующего ему собственного вектора
C++ Использование собственного функтора со связывателями
C++ Не выводится сообшения от деструктора для умного указателя

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

Или воспользуйтесь поиском по форуму:
Philosophistic
0 / 0 / 0
Регистрация: 20.10.2011
Сообщений: 9
27.08.2012, 01:47  [ТС]     Реализация собственного умного укзателя #13
Цитата Сообщение от softmob Посмотреть сообщение
класс умного указателя на подобие auto_ptr. похоже вы первоначально что то типа этого и делали
Да, после некоторых изменений у меня была такая же реализация. И программа все равно не работала, потому что не учел особенности работы auto_ptr

P.S. Выбрал слишком широкий круг задач во время тестирования, для которых auto_ptr не предназначен.

Добавлено через 12 минут
Цитата Сообщение от softmob Посмотреть сообщение
немного переделал под работу на основе счетчика пользователей
Спасибо. Понял, что делал не так
Yandex
Объявления
27.08.2012, 01:47     Реализация собственного умного укзателя
Ответ Создать тему
Опции темы

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