Разрушитель конструктор вызывает - PullRequest
2 голосов
/ 23 марта 2012

Я начинающий программист, и мне было интересно ...

Мне нужен уникальный идентификатор для моего объекта в игре

, поэтому я решил определить глобальный класс, который содержитглобальный идентификатор, и когда я вызываю конструктор объекта, он будет увеличиваться, а при вызове деструктора этого объекта он уменьшается.

Правда ли, что для каждого вызова конструктора будет соответствующий деструктор?

class id_holder{
private:
    int id_count;

public:
    id_holder() {id_count = 0 ; std::cout<< "unique_id: I'm constructed"<<std::endl;}

    ~id_holder(){std::cout<<"unique_id: I'm destructed"<<std::endl;}

    void increment_id(){id_count ++;};
    void decrement_id(){id_count --;};

    int get_id() {return id_count;};

};

class BaseObject {
protected:
    void increment_id();
    void decrement_id();
public:
    virtual ~BaseObject(){decrement_id();}
    BaseObject();
    BaseObject(V2 pos, ObjectType idobj, double s, Color col);
};

BaseObject::BaseObject(){   
    //stuff
    increment_id();
    unique_id = bObj_id_counter.get_id();
}


BaseObject::BaseObject(V2 pos, ObjectType idobj, double s, Color col){
    //stuff
    increment_id();
    unique_id = bObj_id_counter.get_id(); 
}

void BaseObject::increment_id(){
    bObj_id_counter.increment_id();
}

void BaseObject::decrement_id(){
    bObj_id_counter.decrement_id();
}

дополнительный вопрос ... можно ли сравнивать адреса памяти (этого должно быть достаточно уникального идентификатора) объектов вместо использования id_holder?

Ответы [ 5 ]

4 голосов
/ 23 марта 2012

Правда ли, что для каждого вызова конструктора будет соответствующий деструктор?

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

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

можно ли сравнивать адреса памяти (этого должно быть достаточно для уникального идентификатора) объектов вместо использования id_holder

Вы можете сделать это, каждый объект будет иметь уникальный адрес памяти.Это своего рода грязное решение, в зависимости от вашей цели.

3 голосов
/ 23 марта 2012

Нет, это не обязательно так. В каждой правильной программе есть вызов деструктора для каждого вызова конструктора. Но если, например, объекты, построенные с new, не delete d, вызов деструктора не будет.

Кроме того, в вашем примере вы не реализовали конструктор копирования, что означает, что вы могли бы учитывать больше вызовов деструкторов, чем вызовов конструктора.

Кроме того, вы также не реализовали оператор присваивания. Если используется объект по умолчанию, объект, которому назначается, будет иметь тот же unique_id, что и объект, которому он назначен. (Предполагая, что unique_id является членом BaseObject, который вы не объявили в своем фрагменте кода.) Это сделало бы ваш unique_id совершенно «неуникальным». ; -)

1 голос
/ 23 марта 2012

Обычно это называется подсчетом ссылок и имеет широкий спектр применения. Да, это возможно, но ваша пока не будет работать правильно.

  1. Если вам нужен глобальный уникальный идентификатор для всех ваших объектов, вам нужно иметь один id статически, а затем использовать любопытно повторяющийся шаблон , чтобы убедиться, что этот id является глобальным только для определенных типов. Затем каждый тип получает копию глобального id во время построения.
  2. Вам нужно увеличить счетчик в конструкторе копирования
  3. Поскольку increment_id() и decrement_id() вызываются классом id_holder, нет никакой причины вызывать их снова в вашем конструкторе / деструкторе BaseObject.
  4. Он не будет работать при наличии многопоточного доступа, вам нужно найти способ атомарной установки «счетчика ссылок».

Это относительно элегантное решение, которое позволяет вам выполнять такие вещи, как поиск в постоянном времени для элемента по его идентификатору. Например:

Предупреждение псевдокода (не скомпилировано и не протестировано)

template <class T>
class counter
{
   static size_t global_id_;
   size_t id_;

public:
    counter() : id_(global_id_++) {}
    counter(const counter&) : id_(global_id++) {}
    ~counter() {}

    counter& operator=(const counter&)
    {
      // left as an exercise for the reader
      // as what to do in this case is highly 
      // dependent upon the application
    }
};

class counted_object : public counter<counted_object>
{
   // stuff
};

Теперь вы можете хранить таблицу поиска counted_objects, сохраненную в векторе, для очень быстрого поиска:

std::vector<counted_object*> lookup;
counted_object* o416 = lookup[416];
0 голосов
/ 23 марта 2012
  1. Да, для каждого класса будет деструктор, и компилятор выдаст вам значение по умолчанию, если вы его не предоставите. Посмотрите на C ++ по умолчанию деструктор

    1. Хотя вы можете использовать адреса памяти, это не рекомендуется. Может получиться довольно запутанным, особенно. если используется общий ptrs и т. д.
0 голосов
/ 23 марта 2012

Да, это так, и да, вы можете сравнить адреса.Проблема только в том, что у вас есть утечки памяти и объекты не удаляются.

Каждый объект имеет уникальный адрес.Даже если вы создадите пустой класс или структуру, его размер не будет равен нулю (по языку).Будьте осторожны при передаче ссылки this из конструктора при работе с несколькими потоками, поскольку ваш объект может быть не полностью построен.

РЕДАКТИРОВАТЬ: Вы можете использовать это в своих интересах, чтобы обнаружить утечки памяти.Предполагая, что вы удаляете каждый объект, который вы создали к моменту выхода из программы (например, метод очистки), просто посмотрите, остались ли у вас какие-либо объекты.

EDIT2: Вот очень хорошостатья о подсчете объектов в C ++

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...