C++ 使用已使用的内存位置进行动态分配

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 =

我有一个提取运算符用于一个具有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 = *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;
};