Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Простая программа, но есть вопрос
Форум программистов > Системное программирование > C, С++ и С Builder > Общие вопросы по С и С++
michael_is_98
#include <map>

// ---------------------базовый класс - распределения
class ZRV
{
public:
  virtual ~ZRV() {}

  virtual const char*PoluchitNaim()=0;
};

// ---------------------- нормальное распределение --------------
class NormalZRV:public ZRV
{
public:
    // s - среднее, sig - станд.откл.
    NormalZRV(double s, double sig) : s(s), sig(sig),s1("среднее"),sig1("станд.откл."){}
    virtual ~NormalZRV() {}


    const char*PoluchitNaim() { return "нормальное";}

private:
    double s,sig;
    char *s1,*sig1;
};

//-----------------------"умный указатель"-------------------
class PtrZRV
{
public:
    PtrZRV() {;}

    template<class T> PtrZRV(T& ref) :ptr(new T(ref)) {}
    ~PtrZRV()                      
    {
        delete ptr;
    }
private:
    ZRV* const ptr;
};

void main(void)
{
    typedef std::multimap<int, PtrZRV> ut;
    ut a;
    NormalZRV nzrv(1.0, 0.0);
    a.insert(ut::value_type(1,nzrv));
}



Идея проста: есть базовый класс (распределения), на нем построен класс NormalZRV (нормальное распределение). Для базового класса ZRV создан класс "умный указатель".
Класс "умный указатель" используется в STL multimap.
Подскажите, почему после вызова метода insert для одного и того же экземпляра класса PtrZRV деструктор вызывается дважды?
62316e
Чесно это ты писал?
В СТЛ есть такие приколы. Обекти чясто создаютса и удаляютса.
Кароче определи к-тор копирования и обнуляй в нем старый указатель.
michael_is_98
Цитата(62316e @ 21:05:2006, 03:22 ) *
Чесно это ты писал?
В СТЛ есть такие приколы. Обекти чясто создаютса и удаляютса.
Кароче определи к-тор копирования и обнуляй в нем старый указатель.

Конечно.
Думал над конструктором копирования . Но как он будет выглядеть для PtrZRV? Чтобы компилировалось без ошибок.
jo1nt
Я так понимаю, тут создается еще 1 копия:
Цитата
PtrZRV(T& ref) :ptr(new T(ref))
//T(ref) вызывает конструктор копии, со старым объектом ничего не происходит!
соответсвенно,
Цитата
NormalZRV nzrv(1.0, 0.0);
//-1 объект
Цитата
a.insert(ut::value_type(1,nzrv));
// 1+1 =2 объекта.
При выходе из области видимости вызывается деструктор для 2 объектов, чего и следует ожидать( 1 раз для NormalZRV второй для PtrZRV (который вызывает деструктор NormalZRV) .

Шаблон auto_ptr(из mem) реализует деструктивное копирование, то есть уничтожает объект, УКАЗАТЕЛЬ(НЕ ССЫЛКА!!!) на который передается ему в конструкторе. Я бы рекомендовал использовать его (и обращаться к нему проще, и необходимые функции в нем уже написаны).
62316e
Кста, michael_is_98 ты чем компилил?
А вот что поидеи получилось...
#include <map>
class ZRV
{
public:
    virtual ~ZRV() {}
    virtual const char*PoluchitNaim()=0;
};
class NormalZRV:public ZRV
{
public:
    NormalZRV(double s, double sig) : s(s), sig(sig),s1("среднее"),sig1("станд.откл."){}
    virtual ~NormalZRV() {}
    const char*PoluchitNaim() { return "нормальное";}
private:
    double s,sig;
    char *s1,*sig1;
};
class PtrZRV
{
public:
    PtrZRV(const PtrZRV &cpy): ptr()
    {
        //static int i = 0;
        //i++; // i == 2
    }
    template<class T> PtrZRV(T& ref) :ptr(new T(ref)) {}
    ~PtrZRV()                      
    {
            //if (ptr)
        delete ptr;
    }
private:
    ZRV* const ptr;
};

typedef std::multimap<int, PtrZRV> ut;

void main(void)
{
    ut a;
    NormalZRV nzrv(1.0, 0.0);
    a.insert(ut::value_type(1,nzrv));
}
michael_is_98
Разобрался...
Компилировал на VC 5.0... Что-то на нем не получалось сделать из того, что получилось в VC7.0.
Видимо есть недостатки. И STL несколько староват.
Да, auto_ptr лучше... Это и есть "умный указатель"? С его помощью программа идет (но несколько доработал ее). И теперь многие законы распределения вер-тей можно вписать в новую схему...
Спасибо за помощь!
michael_is_98
Цитата(michael_is_98 @ 22:05:2006, 16:32 ) *
Разобрался...
Компилировал на VC 5.0... Что-то на нем не получалось сделать из того, что получилось в VC7.0.
Видимо есть недостатки. И STL несколько староват.
Да, auto_ptr лучше... Это и есть "умный указатель"? С его помощью программа идет (но несколько доработал ее). И теперь многие законы распределения вер-тей можно вписать в новую схему...
Спасибо за помощь!

Все-таки вопросы появились. Убрал свой класс "умного указателя" и использовал auto_ptr. Т.е.

#include <memory>
typedef std::auto_ptr<ZRV> pZRV;

Попытался использовать ассоциативный контейнер map

void main(void)
{
typedef std::multimap<int, pZRV> ut;
ut a;
a.insert(ut::value_type(1,pZRV(new NormalZRV(.0,.0)) ));
}

Компилятор выдает ошибку - нет конструктора копирования у pZRV.
Неужели нельзя использовать класс pZRV в map?
jo1nt
Попробуй так:
typedef std::multimap<int, ZRV> ut;
typedef std::auto_ptr<ZRV> pZRV;
ut a;
a.insert(ut::value_type(1,(pZRV(new NormalZRV(.0,.0))).get()));
// то есть :
//pZRV p1(new ZRV(.0,.0));
//ZRV p2=p1.get();
//a.insert(ut::value_type(1,p2));



Вообще, использование auto_ptr в стандартных контейнерах рисковано, поскольку оператор "=" работает нестандартно(уничтожает rsh). Алгоритмы, модифицирующие последовательность (напр. sort)
скорей всего испортят эту последовательность.
michael_is_98
Цитата(jo1nt @ 27:05:2006, 06:32 ) *
Попробуй так:
typedef std::multimap<int, ZRV> ut;
typedef std::auto_ptr<ZRV> pZRV;
ut a;
a.insert(ut::value_type(1,(pZRV(new NormalZRV(.0,.0))).get()));
// то есть :
//pZRV p1(new ZRV(.0,.0));
//ZRV p2=p1.get();
//a.insert(ut::value_type(1,p2));

Вообще, использование auto_ptr в стандартных контейнерах рисковано, поскольку оператор "=" работает нестандартно(уничтожает rsh). Алгоритмы, модифицирующие последовательность (напр. sort)
скорей всего испортят эту последовательность.

Понятно, а как тогда лучше создать ассоциативный контейнер, который будет содержать структуры различных типов с различными полями. Не создавать же контейнер под каждую конкретную структуру?
С помощью указателей это еще возможно - путем приведения (настройки) указателя на опред. тип.
Что такое rsh?
jo1nt
rsh, вернее rhs(опечатка вышла) - Right Hand Side, то что справа от оператора присваивания, напр. :
int a=10; //a -lhs, 10 -rhs
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2008 IPS, Inc.