2017-10-20 78 views
4

不允許使用載體專門爲這個作業。我發現的大部分答案只是陳述「你應該使用矢量」作爲最受歡迎的評論。雖然我很欣賞並理解這一點,但我僅僅被限制使用它來完成這項任務。插入對象與動態存儲器陣列(無載體允許)C++

它是一個C++分配與動態存儲器管理如下:

// property in header declaration 
int numAnimals; 
int capacity; 
Animal** animals; 
void addAnimal(Animal *newAnimal); 

// class implementation 
capacity = 10; 
numAnimals = 0; 

animals = new Animal*[capacity]; 

void SampleClass::addAnimal(Animal *newAnimal) 
{ 
    for (int i = 0; i < capacity; i++){ 
     if(animals[i]){ 
      // animal object already exists in array, move on 
      i++; 
     }else{ 
      animals[i] = newAnimal; 
      numAnimals++; 
      break; 
     } 
    } 
} 

動物是一個指針的指針,在此情況下的指針的指針數組到對象,它還有待型動物創建。

使用'addAnimal'函數,我試圖做的是通過循環指針數組來添加一個動物對象到數組,如果已經存在動物對象,則迭代到下一個索引。如果沒有動物,那麼將該動物插入數組中。

我得到拋出的異常「讀訪問衝突」,當我試圖訪問一個動物對象的成員函數在數組中。

我懷疑是因爲: 如果(動物[1])可能沒有做什麼,我認爲它在做什麼,通過我從來不打「其他」部分中的調試器來運行它,所以陣列仍然是滿的指針在方法完成時未設置爲任何對象。因此,當我嘗試訪問一個成員函數時,它是一個不存在的對象。

所以,如果我的懷疑是正確的,那麼什麼是插入一個新的對象爲指針,以這種方式數組的最佳方式?他們需要的是三分球,否則它會自動創建數組充分填充物,這是不是我想要的。

我沒有張貼所有的代碼,因爲我想繼續我的問題簡單地說,道歉,我是一個新的C++和一般的計算器。是的,我知道要刪除[]來清除內存。

任何幫助表示讚賞,謝謝!

+1

你已經有了'numAnimals'。簡單地使用它:'動物[numAnimals] = newAnimal;'不要搜索。 – 2017-10-20 10:39:42

+3

'if(animals [i])** **正在測試一個空指針,但是當你從'new'獲得內存時,不能保證指針是空的。無論如何,使用'numAnimals'似乎是一個更好的主意。 –

+0

謝謝@ manni66,快速響應,當你提起它時非常明顯。 sp2danny的答案也是我所尋找的,但我同意你的提示適用於我的用例。 –

回答

4

由於在numAnimals中,您保留了陣列中當前動物指針數量的計數,因此不需要for循環來查找第一個可用插槽以添加新的動物指針(注意,假設您想要使用for循環就像在你的代碼所示,你要注意陣列中的所有初始指針正確初始化到nullptr)。

你可以使用:

// Inside SampleClass::addAnimal(Animal *newAnimal): 

animals[numAnimals] = newAnimal; 
numAnimals++; 

請注意,你必須要注意溢出你的陣列容量,當你插入一個新的動物。
因此,插入一個新的動物之前,你必須檢查是否有足夠的空間在陣列中,例如:

// Before inserting: 
if (numAnimals == capacity) 
{ 
    // You ran out of capacity. 
    // 
    // 1. Allocate a new array with bigger capacity (e.g. 2X) 
    // 2. Copy the content from the current array to the new one 
    // 3. delete current array 
} 

補充說明:

是的,我知道delete[]清除內存之後

請注意,如果你的animals數組的指針上調用delete[] ,你釋放這個指針數組,但是不是Animal obje cts指出。

4
int capacity = 10; 
Animal** animals = new Animal*[capacity]; 

這種分配10個球,除了它確實沒有初始化, 這意味着你有本質上的垃圾數據。

if (animals[i]) 

該測試針對那些nullptr指針之一,但因爲你沒有 沒有初始化,這是不太可能,它的nullptr

您需要添加一個環通是空出來的數據,之後你 分配它:

for(int i=0; i<capacity; ++i) 
    animals[i] = nullptr; 

還有一個錯誤:

if (animals[i]) { 
    // animal object already exists in array, move on 
    i++; // <- here 

這是不對的,你移動兩次for (int i = 0; i < capacity;我+ +)

1

事情是「使用矢量」,儘管你的老師告訴你,否則,是做到這一點的正確方法。但是,如果您應該手動管理動態數組,那麼您可以做的最好的做法是將所有髒內存內容都封裝在class中,並編寫您自己的替換爲std::vector。也就是說,爲了避免動態分配遍佈整個代碼(特別是在應該處理Animal的地方,而不應該在意手動分配內存等),你應該寫一個class來做那個(而不是別的),並且提供一個更好的界面。我只能在這裏概述這個想法:

template <typename T> 
class my_vector { 
    private: 
     T* data; 
     size_t size; 
     size_t capacity; 
    public: 
     void push_back(const T& t); 
     size_t size(); 
     T& operator[](size_t index); 
     void resize(size_t size); 
     //... etc... 
}; 
+0

「使用'std :: vector' ...是做這件事的正確方法」它取決於「它」是什麼。如果「它」正在編寫可維護的生產代碼,那麼我同意。如果「it」正在嘗試指針,以便了解動態內存分配是如何工作的,那麼'std :: vector'沒有多大幫助。 –

+1

@ArthurTacca thx指出來,我的意思是「使用矢量」。即使對於使用類向量類的指針進行實​​驗也是「方式」imho。如果不允許使用'std :: vector',那麼imho應該寫一個自己的替代品 – user463035818