2013-02-04 30 views
0

在一個方法裏面可以從類中創建一個未初始化的對象嗎?C++:在一個方法裏面可以從類中創建一個未初始化的對象嗎?

這裏的一些背景:想象一個類,其中構造所有分配內存:

class NumberArray 
{ 
    size_t m_Size; 
    int *m_Numbers; 

public: 
    NumberArray() { m_Size = 1; m_Numbers = new int[1]; m_Numbers[0] = 0; } 

    // . . . other methods for manipulating or constructing . . . 

    ~NumberArray() { delete[] m_Numbers; } 

    // What if I had a method that concatenates two arrays? 
    NumberArray ConcatenateWith(const NumberArray &) const; 
}; 

裏面這樣的方法人會期望創建NumberArray類的未初始化的對象,然後「結構」基於一個新的對象在this和參數中的對象?又名:

NumberArray NumberArray::ConcatenateWith(const NumberArray &other) const 
{ 
    // Mystery manner of creating an uninitialised NumberArray 'returnObject'. 
    returnObject.m_Size = m_Size + other.m_Size; 
    returnObject.m_Numbers = new int[returnObject.m_Size]; 
    std::copy(m_Numbers, m_Numbers + m_Size, returnObject.m_Numbers); 
    std::copy(other.m_Numbers, other.m_Numbers + other.m_Size, returnObject.m_Numbers + m_Size); 
    return returnObject; 
} 

這樣做的最好方法是什麼?基本上,我不希望默認的構造函數創建一個大小爲1的數組,我將只刪除然後再分配一個新的數組。

+3

我認爲你說出你的問題的方式表明你對對象及其構造有深刻的誤解。我建議閱讀更多的C++材料。 –

+1

添加到Andy Prowl的評論中,我建議您閱讀Lippmann的「C++ Object Model」 –

+1

@Aniket:請記住該書中的某些信息已過時/錯誤。可能會更好地堅持其他的東西。 – GManNickG

回答

1

這並不完全清楚你想要做什麼,但如果你想要的只是創建一個新的類的實例,並沒有一個構造函數調用默認的構造函數,那就做那件事。

您只需要創建一個private構造函數,該構造函數與默認構造函數具有不同的簽名,並且不分配內存(或者以不同於默認構造函數的任何方式進行區分);那麼只需在必要時讓你的類在內部調用該構造函數。

0

據我所知,沒有明確定義的方式來創建一個對象而不調用它的構造函數。這與您是否可以訪問其公共接口無關,但您可以實施私有或受保護的構造函數,以限制可以調用它的人員。從它自己的內部方法中創建類的新實例沒有任何限制,實際上,如果要限制在哪個條件下所述對象,則定義一個私有構造函數和一個創建所述對象的實例的靜態公共方法是很常見的可以創建。

如果需要,可以爲對象分配足夠的內存,並將指向該內存的指針reinterpret_cast重新指向所需類型的指針。這通常適用於POD,但由於C++中的多態繼承的許多實現(如果不是全部)添加了一個指向多態實例的vtable的指針,因此這種方法通常(如果不是總是如此)通常會失敗。

總之,創建一個私有構造函數,並有一個靜態方法調用它,然後做任何其他工作,你需要的是我的建議。

0

我想你想要什麼,「匿名」類各種各樣的這一可能類似於:

struct test { 
    virtual void doSomething() { 
     puts("test"); 
    } 
}; 

struct a { 
    test *t() { 
     struct b : test { 
      void doSomething() { 
       puts("b"); 
      }; 
     }; 

     return new b; 
    }; 
}; 

int main() 
{ 
    a a; 

    a.t()->doSomething(); // outputs 'b' 
} 

然而,由於切片以及如何new作品在C++,你必須返回一個指針和'匿名'類型必須有一個名稱,即使它僅限於該函數。

如果您可以編輯OP並明確說明您希望完成的任務,也許我們可以幫助您更多。

+0

這不會導致內存泄漏? – Veltas

+0

@Veltas正確。返回指針時要小心另一件事。這只不過是OP可能需要的PoC,它不是一種無缺陷的解決方案。 –

+0

爲什麼你返回一個指針,爲什麼不返回對象本身? – Veltas

1

你要求的是安置新。這看起來是這樣的:

#include <cstdlib> 
#include <new> 

void* mem = std::malloc(sizeof(T)); // memory for a T (properly aligned per malloc) 

T* x = new (mem) T; // construct a T in that memory location 
x->~T();   // destruct that T 

std::free(mem); // and free the memory 

正確地這樣做(在適當的管理和對齊的內存異常安全的方式)並不是一個簡單的任務。你需要小心你的對象的生命週期。

對於您的問題,您正在準確描述std::vector的功能。它分配原始未初始化的內存並將插入的元素直接構造到該內存中。它的許多代碼致力於使生命週期和內存管理正確和異常安全!

您應該更願意使用std::vector而不是自己寫。

相關問題