[英]Why isn't my dynamically allocated array holding the correct values?
我們正在討論我學校的課程主題。 我應該創建一個名為Student的類,我們可以使用它在動態分配的數組中保存不同的測試分數。 我正在努力弄清楚為什么當我打印出此類的特定實例的數組時,為什么會給我完全不正確的值。 我知道我的班級設置函數正在設置正確的值,但是每當我打印出來時,它們都是完全錯誤的。 下面是我的代碼。 main()中被注釋掉的部分僅用於測試makeArray()函數的邏輯。
#include <iostream>
using namespace std;
class Student {
private:
string name;
int id;
int* testptr;
int num;
void makeArray() {
int array[num];
testptr = &array[num];
for (int i = 0; i < num; i++) {
array[i] = 0;
}
}
public:
Student() {
setName("None");
setID(10);
num = 3;
makeArray();
}
Student(int n) {
setName("None");
setID(10);
if (n > 0)
num = n;
else
num = 3;
makeArray();
}
Student(string nm, int i, int n) {
setName(nm);
setID(i);
if (n > 0)
num = n;
else
num = 3;
makeArray();
}
void setName(string nm) {
name = nm;
}
void setID(int i) {
if (i >= 10 && i <= 99){
id = i;
}
else {
cout << "Error: Cannot set id to " << i << " for " << getName();
id = 10;
}
}
void setScore(int i, int s) {
if ((i >= 0 && i <= num) && (s >= 0 && s <= 100)) {
//Here is where I set the values for the array. They come out correct in the console.
testptr[i] = s;
cout << testptr[i] << endl;
} else {
cout << "The test " << i << " cannot be set to " << s << " for " << getName() << endl;
}
}
string getName() const {
return name;
}
int getID() const {
return id;
}
void showScore() {
//This is where I print out the values of the array. They come out incorrect here.
for (int i = 0; i < num; i++) {
cout << "Test " << i << " had a score of " << testptr[i] << endl;
}
}
void display() {
cout << "Calling the display function" << endl;
cout << "The Name: " << getName() << endl;
cout << "The ID: " << getID() << endl;
showScore();
}
~Student() {
}
};
int main() {
Student c("Joe", 40, 5);
c.setScore(0, 90);
c.setScore(1, 91);
c.setScore(2, 92);
c.setScore(3, 93);
c.setScore(4, 94);
c.display();
/**int* testpointer;
int num = 3;
int array[num];
testpointer = &array[0];
for (int i = 0; i < num; i++) {
testpointer[i] = i;
cout << testpointer[i] << endl;
}**/
}
問題(實際上是一系列問題)在此功能中
void makeArray() { int array[num]; testptr = &array[num]; for (int i = 0; i < num; i++) { array[i] = 0; } }
由於num
不是編譯時常量,因此第一條語句int array[num]
是無效的C ++。 如果您的編譯器支持它,則它是編譯器特定的擴展。 (從技術上講,這是一個可變長度數組,這是1999 C標准中C的功能,2011年以來C中的可選功能,但從未在任何標准或草案中成為C ++的一部分。)
其次,如果您的編譯器確實支持該構造,則它將創建一個自動存儲持續時間的數組,該函數在函數返回時將不復存在。 這意味着testptr
然后包含一個懸空指針。 函數返回后,任何對testptr
取消引用(例如訪問數組元素)都將給出未定義的行為。
如果確實必須使用動態內存分配,請使用“新表達式”,例如testptr = new int[num]
。 只需記住,然后有必要在您的類析構函數中delete [] testptr
。 還要查找“三元規則”,因為在創建類的其他實例時,您將需要編寫副本構造函數和賦值運算符來正確管理數組。
更好的是, #include <vector>
,並將testptr
更改為std::vector<int>
。 閱讀有關標准向量類的文檔,以了解如何使用它,包括管理其大小。
同樣, #include <string>
也是如此。 沒有它,您的代碼就不需要編譯使用std::string
類型的代碼-您很幸運,在實現中, <iostream>
包括<string>
。 這不是C ++標准所必需的,實際上,某些編譯器而不是其他編譯器會發生這種情況。
您的代碼中也存在其他問題,但是以上內容足以使您入門。
您的代碼中存在多個問題,但讓我們先從問題開始。 問題在於,在當前的實現中,您不是在使用動態數組,而只是在內存中指向某些隨機數據的指針。 使用new
運算符創建動態分配的對象。 在您的情況下,您可以在堆棧上分配對象:
void makeArray() {
int array[num]; // creates local object on stack
testptr = &array[num]; // stores pointer to local object
for (int i = 0; i < num; i++) {
array[i] = 0;
}
} // stack is being destroyed here along with array object
// testptr points to memory that should no be addressed anymore
在C ++中,很常見的錯誤是返回/存儲指針或對聲明該對象的作用域之外的本地對象的引用。 初始化指針的正確方法是:
void makeArray() {
// note parenthesis at the end,
// default zero-initializer will be called
testptr = new int[num]();
}
請注意,在這種情況下,您必須記住在不需要使用更多內存時釋放它們。 最好的方法是將delete調用放入析構函數中:
~Student() {
delete[] array;
}
然后,當Student對象超出范圍時,將釋放內存。
但是,我強烈建議您熟悉“智能指針”的概念,這些概念是專門為減少手動內存管理工作而設計的。 在現代C ++中,“原始”指針由於可能導致許多錯誤而被認為是非常不好的做法。 更好的方法是根本不使用指針,而是使用一個標准C ++容器,例如std::vector<int>
為了使類中的函數共享數據,可以在類范圍內聲明變量。
class Foo
{
public:
MyFunc1() { _n = 1; }
MyFunc2() { _n = 2; }
private:
int32_t n; // can be used by all member functions
};
在您的情況下,您在函數作用域聲明了一個數組,一旦離開函數,該數組將被銷毀。
另外,您不能在堆棧上聲明大小可變的數組,而需要在堆上分配該數組
class Foo
{
public:
Foo():_array(nullptr),_size(0) {}
void AllocateArray(int size) { _array = new int32_t[size]; _size = size; }
void DestroyArray() { delete [] _array; _size = 0; }
private:
int32_t* _array;
int8_t _size;
};
通常,您將為此使用一個C ++容器(例如std :: vector),而不是使用原始指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.