簡體   English   中英

析構函數構造函數調用

[英]Destructor Constructor calls

我是初學程序員,我想知道......

我需要一個游戲中我的對象的唯一ID

所以我認為我定義了一個包含全局id的全局類,當我調用一個對象的構造函數時它會遞增,而在調用該對象的析構函數時它會遞減它。

對於每個構造函數調用都會有相應的析構函數嗎?

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),而不是使用id_holder?

對於每個構造函數調用都會有相應的析構函數嗎?

是的,除非您使用operator new分配對象並且不銷毀它們,或者您的應用程序異常終止。

您的解決方案應該運行良好,除非您同時使用它。 如果您這樣做,您應該提供對該全局對象的獨占訪問權限,但我不認為是這種情況。

是否可以比較對象的內存地址(這應該是一個唯一的id),而不是使用id_holder

你可以這樣做,每個對象都有一個唯一的內存地址。 這是一種骯臟的解決方案,取決於您的目標。

不,這不一定是真的。 在每個表現良好的程序中,每個構造函數調用都有一個析構函數調用。 但是,例如,如果使用new構造的對象不是delete d,則不會有析構函數調用。

此外,在您的示例中,您沒有實現復制構造函數,這意味着您可能會考慮比構造函數調用更多的析構函數調用。

此外,您也沒有實現賦值運算符。 如果使用默認對象,則分配給的對象將具有與分配的對象相同的unique_id (假設, unique_id是您未在代碼片段中聲明的BaseObject的成員。)這樣就會使您的unique_id非常“獨特”。 ;-)

這通常稱為“引用計數”,它具有廣泛的用途。 是的,這是可能的,但你的工作還不太正常。

  1. 如果您想要所有對象的全局唯一標識符,則需要靜態保存一個id ,然后使用奇怪的重復模板模式來確保此id僅對特定類型是全局的。 然后每種類型在構造期間獲得全局id的副本。
  2. 您需要在復制構造函數中遞增計數器
  3. 由於increment_id()decrement_id()id_holder類調用,因此沒有理由在BaseObject構造函數/析構函數中再次調用它們。
  4. 它不會在存在多線程訪問的情況下工作,您需要找到一種原子設置“引用計數”的方法。

這是一個相對優雅的解決方案,允許您對給定ID的項目執行常量查找等操作。 例如:

警告偽代碼(未編譯或測試)

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];

是的,它是,是的,你可以比較地址。 唯一的問題是如果您有內存泄漏並且對象沒有被刪除。

每個對象都有一個唯一的地址。 即使您創建一個空類或結構,它的大小也不會為零(通過語言設計)。 在處理多個線程時從構造函數傳遞this引用時要小心,因為您的對象可能未完全構造。

編輯:你可以利用這個來發現內存泄漏。 假設您在程序退出時刪除了您創建的每個對象(如清理方法),只需查看是否還有任何對象。

EDIT2: 這是一篇關於C ++中對象計數的非常好的文章

  1. 是的,每個類都會有一個析構函數,如果你沒有提供默認值,編譯器會給你一個默認值。 看看C ++默認析構函數

    1. 雖然您可以使用內存地址,但不建議使用。 特別是,可以得到相當混淆。 如果使用共享ptrs等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM