iT邦幫忙

1

問c++相關問題

版上的各位大家好,我是一個C++新手,來問一些觀念!
https://ideone.com/e0fFAE
這是我的練習內容,我目前遇到一些困難!
在程式內我有註解
CHuman ,CEmployee解構式如果要delete[] 就會讓資料消失了!可是觀念上new 跟delete要成對才對,還是我應該怎麼正確地去delete呢

CEmployees 建構式裡的new是不是應該要一開始就寫上,我理解應該要這樣寫第一筆資料才能順利Add進去,但是指導者跟我說我這樣new了兩次(我解釋說我有在函式內delete mEmployees 但是他說我觀念有誤) 請問這邊我有出現甚麼問題嗎,拜託各位大大!

淺水員 iT邦研究生 2 級 ‧ 2020-05-01 14:17:59 檢舉
有規定不能用 std::string 嗎?
1
海綿寶寶
iT邦大神 1 級 ‧ 2020-05-01 10:15:01

如果不是規定一定要用 array 的話
建議可以考慮看看
Vector

根據該網友的說法

C/C++ array’s size do not change dynamically

基本上無法達到「動態」陣列的目的
頂多就是 delete then define 的做法
就算做出來了
也是很不仗義的做法
(為了加/減一個 element,要整個陣列複製來複製去的)

1
淺水員
iT邦研究生 2 級 ‧ 2020-05-01 15:08:04

看到的問題

只是比較粗略的看一下
這些改好還有其他問題再討論

62行:NewEmployees[index] = mEmployees[count];

這邊是不是要寫 NewEmployees[index] = mEmployees[index];
另外這邊的 = (assign) 要另外處理
否則裡面的 CEmployee.mId 及 CHuman.mName 只會複製指標
但是該指標所指的位址卻因為64行的 delete 連帶被釋放了

92行:cin>>name;

這邊 name 的資料型態是 char*,其所指的空間只有1個 char
所以這邊應該是會超出所宣告的記憶體空間
這會造成程式錯誤或崩潰

98行:cin>>id;

同 92 行問題

關於動態空間的寫法

需要動態空間的話大概可以這樣

//====資料====
SomeType(某資料型態) *p;
int capacity; //容量
int index; //寫入到哪邊,0<=index<capacity

//===建構===
p=new SomeType(基礎長度)
capacity=基礎長度
index=0

//===寫入===
if(index+寫入的長度>=capacity) {
    擴充容量(並更新capacity)
}
寫入資料(並更新 index)

PS. 擴充容量的方式有很多種,常見的方式是每次容量乘以2

0
wwx
iT邦好手 1 級 ‧ 2020-05-02 16:05:19

最大的問題在CHuman的new/delete要能成對,
如果沒調用過SetName就沒有new過,
而解構固定delete的話當然就會出錯了

所以可以這樣調整
建構時先給予初值為空
mName = NULL;
解構時,判斷不為空才delete
if (mName) delete[] mName;

同樣的,所謂new了兩次的問題,可在SetName加以預防,
在new之前先判斷如果不為空要先delete,
這跟剛剛解構裏所加的程式碼相同,
if (mName) delete[] mName;

弄懂前述大原則後, 就能寫出所有正確的邏輯方式,
指導員就不會說你觀念有誤了, 至於其他小問題自行除錯吧!

0
kphuang
iT邦見習生 ‧ 2020-05-03 05:46:03

先寫出正確的程式碼

首先想要正確新增CEmployee
下面的程式碼會有問題

NewEmployees[index] = mEmployees[count];

這樣只會把mEmployees[count]的元素複製到每個NewEmployees[index]中
正確程式碼應該為

NewEmployees[index] = mEmployees[index];

delete[] mName; 是必須嗎?

程式會當掉可以用cout看出原因

cout << "debug 2\n";
delete[] mName;
...
cout << "debug 1\n";
delete[] mEmployees;

加上除錯訊息後delete的順序

debug 1
debug 2
debug 2

"debug 2"跑了兩次,可見delete[] mEmployees;也會跑CHuman的解構子亦即delete[] mName;
那new與delete還會一定要成對嗎?

先寫程式碼驗證

mEmployees = new CEmployee[count+1];//請問這行可以省略嗎
如果不在建構的時候就設置空間 是不是就不能成功Add第一筆

這可以寫程式碼驗證
例如寫一個List方法確認有沒有新增CEmployee成功,

void List() {
    CEmployee * e = NULL;
    for (int i = 0; i < count; ++i)
    {
        e = &mEmployees[i];
        cout << "ID:  " << (*e).GetId() << "\n"
             << "姓名: " << (*e).GetName() << "\n"
             << "年齡: " << (*e).GetAge() << "\n";

    }
}

新增成功後,呼叫List去看列出來的結果

...
Employees.Add(Employee);
cout<<"Finish !\n";
Employees.List();
...

用什麼資料型態或結構去描述系統

可以先思考什麼型態較適合描述員工登錄/查詢系統
若員工人數有限制,例如100人,那CEmployee[100]可以搞定

class CEmployees {
private:
    CEmployee mEmployees[100];
    int count;
...
}

若員工人數無限制,那vector<CEmployee>比較適合

class CEmployees {
private:
    vector<CEmployee> mEmployees;
    int count;
...
}

希望有幫助到你

我要發表回答

立即登入回答