【问题标题】:Memory Management with Command Pattern使用命令模式进行内存管理
【发布时间】:2013-06-21 10:44:27
【问题描述】:

所以,我有以下命令模式实现,它包含在 std::map<CString, IWrite*> commandMap 中:

class IWrite
{
protected:
   CStdioFile* fileWriter;

public:
   IWrite(CStdioFile* _fileWriter)
      : fileWriter(_fileWriter)
   {
   }

   virtual ~IWrite()
   {
   }

   virtual BOOL exec() = 0;
};

class FloatWrite : public IWrite
{
private:
   float input;

public:
   FloatWrite(CStdioFile* _fileWriter, float _input)
      : IWrite(_fileWriter), input(_input)
   {      
   }

   BOOL exec()
   {
      CString fieldvalue;
      fieldvalue.Format("%f", input);
      fileWriter->WriteString(fieldvalue);

      return TRUE;
   }
};

我遇到的问题是我的静态分析工具抱怨fileWriterIWrite 的析构函数中没有被释放或归零。但是,通过在析构函数中添加delete fileWriter,当我在调用std::map.clear() 之前删除映射中的命令模式对象时出现内存访问错误,如下所示:

// free map memory
for ( std::map<CString, IWrite*>::iterator mapItr = commandMap.begin();
      mapItr != commandMap.end();
      ++mapItr)
{
   delete mapItr->second;
}
commandMap.clear();

我在这里错误地处理内存管理吗?我没有对 STL 地图做过很多工作,所以我不熟悉惯用的方法。

编辑:我如何向地图添加元素:

void FooClass::initCommandMap(const MSG_DATA_STRUCT * msgdata)
{
   // Write a float, foo
   commandMap[_T("foo")] = new FloatWrite(&fileWriter, msgdata->foo);
   // Write an unsigned int, bar
   commandMap[_T("bar")] = new UIntWrite(&fileWriter, msgdata->bar);
   // etc...
}

每次用户选择写出数据时都会调用它,因此各种exec() 使用的fileWriter 对象与用户选择的文件是当前的。

注意CStdioFile fileWriterFooClass的成员变量。

【问题讨论】:

  • 您可能需要申请Rule of Three
  • @n.m.这不是三规则(还...),这只是了解谁应该拥有这些对象的情况。
  • @Roddy:一个导致另一个。
  • @n.m.好的,如果我这样做,我会将delete fileWriter 放在IWrite 的析构函数中,还是将FloatWrite 和它的同类放在一起?
  • @cjm571 - 解释为什么要使用指针,以及创建对象的位置以及方法。您可能根本不应该使用指针......

标签: c++ memory-management command-pattern


【解决方案1】:

为什么要保留指向 fileWriter 的指针?据我所知,您的 Command 对象假定在可以使用该命令之前应该存在一个编写器。它也不应该尝试管理 writer 对象,因为它可以由多个命令对象共享。 尝试保留参考。

class IWrite
{
protected:
   CStdioFile &fileWriter;

public:
   IWrite(CStdioFile &_fileWriter)
      : fileWriter(_fileWriter)
   {
   }

   virtual ~IWrite()
   {
   }

   virtual BOOL exec() = 0;
};

【讨论】:

  • 这不是违法的吗? CStdioFileCObject 的子代,不可复制。所以初始化列表中的fileWriter(_fileWriter)会导致编译错误
  • 不应该,至少下面的代码用 g++ 编译:pastebin.com/dnTqQ7wK。你能显示你的代码和你得到的错误信息吗?
  • @cjm571 这不是副本;它是一个 reference 成员。确保您的成员是参考变量;不是平面实例变量。
  • @Grigory 当我添加fileWriter = dataIn.fileWriter; 时,dataInoperator = 重载中的IWrite&amp; 参数,我收到错误C2248: 'CObject::operator =' : cannot access private member declared in class 'CObject' 请注意这是在更改@987654331 之后@成为CStdioFile &amp;
  • 另外,这也是我使用指针的最初原因。由于我的地图值为IWrite*,因此从未使用过IWriteoperator =,因此也不需要CObject::operator =
猜你喜欢
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
相关资源
最近更新 更多