Простая программа, но есть вопрос

Тема в разделе "Общие вопросы по С и С++", создана пользователем michael_is_98, 20 май 2006.

  1. michael_is_98

    michael_is_98 Member

    Регистрация:
    15 окт 2005
    Сообщения:
    14
    Симпатии:
    0
    Код (Text):
    #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 деструктор вызывается дважды?
     
  2. 62316e

    62316e Гость

    Чесно это ты писал?
    В СТЛ есть такие приколы. Обекти чясто создаютса и удаляютса.
    Кароче определи к-тор копирования и обнуляй в нем старый указатель.
     
  3. michael_is_98

    michael_is_98 Member

    Регистрация:
    15 окт 2005
    Сообщения:
    14
    Симпатии:
    0
    Конечно.
    Думал над конструктором копирования . Но как он будет выглядеть для PtrZRV? Чтобы компилировалось без ошибок.
     
  4. jo1nt

    jo1nt Гость

    Я так понимаю, тут создается еще 1 копия:
    //T(ref) вызывает конструктор копии, со старым объектом ничего не происходит!
    соответсвенно,
    //-1 объект
    // 1+1 =2 объекта.
    При выходе из области видимости вызывается деструктор для 2 объектов, чего и следует ожидать( 1 раз для NormalZRV второй для PtrZRV (который вызывает деструктор NormalZRV) .

    Шаблон auto_ptr(из mem) реализует деструктивное копирование, то есть уничтожает объект, УКАЗАТЕЛЬ(НЕ ССЫЛКА!!!) на который передается ему в конструкторе. Я бы рекомендовал использовать его (и обращаться к нему проще, и необходимые функции в нем уже написаны).
     
  5. 62316e

    62316e Гость

    Кста, michael_is_98 ты чем компилил?
    А вот что поидеи получилось...
    Код (Text):
    #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));
    }
     
  6. michael_is_98

    michael_is_98 Member

    Регистрация:
    15 окт 2005
    Сообщения:
    14
    Симпатии:
    0
    Разобрался...
    Компилировал на VC 5.0... Что-то на нем не получалось сделать из того, что получилось в VC7.0.
    Видимо есть недостатки. И STL несколько староват.
    Да, auto_ptr лучше... Это и есть "умный указатель"? С его помощью программа идет (но несколько доработал ее). И теперь многие законы распределения вер-тей можно вписать в новую схему...
    Спасибо за помощь!
     
  7. michael_is_98

    michael_is_98 Member

    Регистрация:
    15 окт 2005
    Сообщения:
    14
    Симпатии:
    0
    Все-таки вопросы появились. Убрал свой класс "умного указателя" и использовал 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?
     
  8. jo1nt

    jo1nt Гость

    Попробуй так:
    Код (Text):
    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)
    скорей всего испортят эту последовательность.
     
  9. michael_is_98

    michael_is_98 Member

    Регистрация:
    15 окт 2005
    Сообщения:
    14
    Симпатии:
    0
    Понятно, а как тогда лучше создать ассоциативный контейнер, который будет содержать структуры различных типов с различными полями. Не создавать же контейнер под каждую конкретную структуру?
    С помощью указателей это еще возможно - путем приведения (настройки) указателя на опред. тип.
    Что такое rsh?
     
  10. jo1nt

    jo1nt Гость

    rsh, вернее rhs(опечатка вышла) - Right Hand Side, то что справа от оператора присваивания, напр. :
    Код (Text):
    int a=10; //a -lhs, 10 -rhs
     
Загрузка...

Поделиться этой страницей