我正在练习使用指针来创建对象和访问数据。我创建了一个名为BigNum的stuct来表示一个多位数的数字。当我尝试在readDigits函数中打印结构的内容时,可以很好地打印它。但是,在将指针传递给main函数之后,stuct的内容被打印成随机数。为什么?如何解决?
struct BigNum{
int numDigits; //the number of digits
int *digits; //the content of the big num
};
int main(){
BigNum *numPtr = readDigits();
for (int i=0; i<(numPtr->numDigits);i++ ){
std::cout << (numPtr->digits)[i] << std::endl;
}
return 0;
}
BigNum* readDigits(){
std::string digits;
std::cout << "Input a big number:" << std::endl;
std::cin >> digits;
int result[digits.length()];
toInt(digits,result);
BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = result;
/* When I try to print in here, it's totally okay!
std::cout << "Here is the content:" << std::endl;
for (int i=0; i<numPtr->numDigits;i++ ){
std::cout << (numPtr->digits)[i] << std::endl;
}
*/
return numPtr;
}
void toInt(std::string& str, int result[]){
for (int i=0;i<str.length() ;i++ ){
result[str.length()-i-1] = (int)(str[i]-'0');
}
}
答案 0 :(得分:1)
您有未定义的行为,因为您将自动对象的地址分配给digits
指针。当readDigits()
返回时,此内存不再有效。您应该为此指针分配基于堆的对象(或某些等效对象,例如使用向量或智能指针):
#include <vector>
struct BigNum{
int numDigits; //the number of digits
std::vector<int> digits; //the content of the big num
};
然后你可以用这种方式将数字插入向量:
int input;
while ( std::cin >> input) //enter any non-integer to end the loop
{
digits.push_back(input);
}
答案 1 :(得分:1)
BigNum* readDigits(){
//....
int result[digits.length()];
//....
numPtr->digits = result;
return numPtr;
}
result
存储在堆栈中。因此,如果您将其作为numPtr
的一部分返回,则退出该函数后它将无效。不必将其存储在堆栈中,您必须使用new
分配它。
答案 2 :(得分:0)
问题是在函数BigNum* readDigits()
中你将apointer分配给堆栈内存到你新分配的BigNum的指针:
int result[digits.length()]; // <--- variable is on the stack!!!
toInt(digits,result);
BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = result; // <--- make pointer to stack memory available to caller of readDigits
现在,如果继续访问numPtr-&gt;数字是正确的,因为结果的内存在堆栈上仍然有效(只要你在readDigits中)。一旦你离开'readDigits()',结果的内存将被覆盖,具体取决于你做什么(调用其他函数,......)。
现在我甚至想知道你为什么不用'int result [digits.length()];'得到编译器错误'因为'digits.length()'不是常数和所需堆栈内存的大小必须在编译时定义...所以我认为结果的大小实际上是0 ... ??测试会是一件好事!
我的建议是修改readDigits的代码,如下所示:
BigNum* readDigits()
{
std::string digits;
int i;
std::cout << "Input a big number:" << std::endl;
std::cin >> digits;
//int result[digits.length()];
//toInt(digits,result);
BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = (int *)malloc(sizeof(int) * numPtr->numDigits); // allocate heap memory for digits
toInt(digits, numPtr->digits);
/* When I try to print in here, it's totally okay!
std::cout << "Here is the content:" << std::endl;
for (i = 0; i <numPtr->numDigits; i++)
{
std::cout << (numPtr->digits)[i] << std::endl;
}
*/
return numPtr;
}
如果不再使用'BigNum * numPtr'('free(numPtr-&gt; digits);'),请记住释放你的记忆。否则你会得到内存泄漏(迟早):
int main()
{
BigNum *numPtr = readDigits();
int i;
for (i = 0; i < (numPtr->numDigits); i++)
{
std::cout << (numPtr->digits)[i] << std::endl;
}
free(numPtr->digits); // free memory allocated by readDigits(..)
return 0;
}