C++ 使用已使用的内存位置进行动态分配
我有一个提取运算符用于一个具有char*成员“name”的类。以下是我的主驱动程序的代码:C++ 使用已使用的内存位置进行动态分配,c++,memory,dynamic,C++,Memory,Dynamic,我有一个提取运算符用于一个具有char*成员“name”的类。以下是我的主驱动程序的代码: Player tempPlayer; for(int i=0;i<4;i++){ fin >> tempPlayer; } stringCopy正文: void stringCopy(char *destPtr, const char *sourcePtr){ while(*sourcePtr!='\0'){ *destPtr =
Player tempPlayer;
for(int i=0;i<4;i++){
fin >> tempPlayer;
}
stringCopy正文:
void stringCopy(char *destPtr, const char *sourcePtr){
while(*sourcePtr!='\0'){
*destPtr = *sourcePtr;
destPtr++;
sourcePtr++;
}
*destPtr='\0';
}
我一直在通过打印出用于temp
的内存地址和名称进行调试
第一次调用提取操作符时,播放器的名称和temp
数组具有不同的内存地址,这是应该发生的。然后删除temp并将其设置为NULL,我通过打印地址(并获取“0”)确认了这一点,并且在函数返回后,播放器名称的地址仍然保留
但是,在随后的呼叫中,temp
的地址和玩家的名字都会与第一个玩家的名字的地址相同。名称地址应该是相同的,因为它是刚刚被覆盖的同一个对象,但是如果使用新字符[]
关键字分配,为什么temp
会获得与“name”相同的地址
以下是调试时使用的一些代码:
沿着操作员身体中的每一步:
ifstream& operator>>(ifstream& fin, Player& currentPlayer){
char* temp = new char[50];
char tempChar;
fin >> temp;
// importing from a file that contains names of about 6 characters each
stringCopy(currentPlayer.name, temp);
delete[] temp;
temp = NULL;
return fin;
}
cout当您delete[]
您已经new[]
ed的内容时,标准库允许重用该内存。因此,temp
一次又一次地得到相同的地址也就不足为奇了。这是预期的行为,而不是问题本身
真正的问题是,在您的“驱动程序”代码(您没有向我们展示的代码)中,您在某个地方有一个templayer
的浅拷贝。这将复制指向name
的指针,而不分配新存储。当该副本被删除时,Player
的析构函数将删除此浅副本中的name
,并将name
释放到堆中
现在,原始文件将指向已释放的内存。未来对操作员>>
的调用会分配现在假定的可用内存。哎呀
您的短期解决方案是删除浅拷贝。从长远来看,正确的解决方法是按照“规则3”(Rule of 3)实现适当的复制和复制赋值构造函数,或者如果您想要真正对C++11友好,则使用规则5。(同一链接。)
交替地,您可以考虑将复制和复制赋值构造器私有化,这将防止这些对象的不必要拷贝。(此处有一些提示:)
向我们展示stringCopy函数的代码。如果你使用C++,那么你可能应该使用STD::string。为什么你说代码< String拷贝< /C>?做一个“深”拷贝?name
也是一个对象吗?请发布stringCopy
和Player
。那么,实际上有问题吗?如果将动态内存分配给一个现在空闲但曾经分配过时间的内存位置,则无需担心。“name”的声明只是char*name
向我们展示Player
的构造函数。例如,当我看到name
没有初始化并且正在从堆栈中拾取垃圾时,我不会感到惊讶。我最初在问题中没有非常清楚地说明这一点,但问题是在为temp
分配内存的第二次调用中,新内存的地址与已在使用的名称
数组的地址相同。是的,temp
获得相同的内存没有问题,因为您已通过delete[]
将其释放以供重用。或者你是说¤tPlayer.name==temp
?这不应该发生。向我们展示调试代码打印的输出。@user1362548:向我们展示player类以及.name的内存是如何分配/释放的……@Joe Z,这就是我的意思。第一次调用的输出:temp address后接name address:0x8ed500 0x8ea2e0
将temp设置为NULL后:temp address和name address:0 0x8ea2e0
第二次调用:temp address和name address:0x8ea2e0
第二次调用后设置为NULL:temp address和name address:00x8ea2e0
顺便说一句,注释位于您的答案代码中,我在这里做一些事情,我只知道它与所问的问题无关。
Player::Player(){
name = new char[50];
stringCopy(name,"name");
ID = new int[5];
}
class Player{
public:
char* name;
};