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

С++ для начинающих

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

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

25.08.2012, 10:18. Просмотров 2289. Ответов 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
#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
, то никаких проблем не возникает. Указатель в исходнике ссылается на структуру.

Подскажите, пожалуйста, в чем может быть проблема.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.08.2012, 10:18
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Реализация собственного умного укзателя (C++):

Реализация умного указателя - C++
Добрый вечер. Сегодня с умным указателем поиграться. Написал обгортку : #pragma once template &lt;typename T&gt; class UniquePtr { ...

Степенной метод нахождения наибольшего по модулю собственного значения и соответствующего ему собственного вектора - C++
Привет всем. Есть код программы, но почему то он не работает, подскажите в чем дело, может ввожу неправильно. Тестовый пример: ...

Реализация собственного оператора "запятая" - C++
Всем привет. Подскажите как самому реализовать оператор запятая. Я хочу реализовать как в векторе. vector&lt;int&gt; v; v +=...

Запись в собственного класса бинарный файл собственного - C++
есть Свой тип данных дробь. Надо реализовать запись и загрузку в\из бинарного файла. #ifndef RATION_H #define RATION_H #include...

Код умного будильника - C++
Нужен код умного будильника или же хотя бы его части .

Задача про умного и скупого бедняка - C++
Однажды умный бедняк попросил у скупого богача приюта на две недели, причем сказал: ’За это я заплачу тебе в первый день 1 рубль, во...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
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
~ Эврика! ~
1243 / 992 / 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
Модератор
6556 / 5022 / 464
Регистрация: 14.02.2011
Сообщений: 16,763
27.08.2012, 01:02 #7
Цитата Сообщение от Philosophistic Посмотреть сообщение
this->ptr
уже куда то указывает???
может сначала память выделим?
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
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
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
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. не пользовался умными указателями, их реализацию тоже до этого не писал. возможно что то не так...
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 Посмотреть сообщение
немного переделал под работу на основе счетчика пользователей
Спасибо. Понял, что делал не так
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.08.2012, 01:47
Привет! Вот еще темы с ответами:

Проверить правильность реализации умного указателя - C++
? template&lt;class T&gt; class Auto_Ptr { public: Auto_Ptr(); explicit Auto_Ptr(T* alloc); virtual ~Auto_Ptr(); ...

Не выводится сообшения от деструктора для умного указателя - C++
#ifndef Shared_ptr_H #define Shared_ptr_H template&lt;class T&gt; class shared_ptr { private: struct storage { T*...

Создание игры с++ любой совет умного человека - C++
Всем доброго времени. Я студент первого курса, изучали мы с++ весь этот период, сейчас в рамках курсовой надо за месяц написать игрушку,...

Передача умного указателя в функцию принимающую указатель на указатель - C++
Итак имеется функция со следующим параметром: HRESULT __stdcall Function(SomeClass **param); В случае, когда создаём обычный...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
27.08.2012, 01:47
Ответ Создать тему
Опции темы

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