如何一次重置大量的类成员,而不是在析构函数中?

时间:2011-01-10 16:19:16

标签: c++ memory-management smart-pointers auto-ptr

我有一个包含许多简单类类型成员的类。更重要的是,随着我继续开发,它们的数量正在增长。

我需要能够立即重置它们,我想在不复制粘贴的情况下完成它们。代码目前看起来像:

typedef auto_ptr<odbc::PreparedStatement> Stmt;

class DbProxy {
private:
  void reset();

  Stmt a;
  Stmt b;
  Stmt c;
  // ... about 10 more
};

void DbProxy::reset()
{
  a.reset();
  b.reset();
  c.reset();
  // etc.
}

显然,我不喜欢将每个新成员添加到reset()函数中(只是因为忘记了一个而导致了一个段错误。)

我打算做的是将它们全部收集到一个结构中,并在auto_ptr下分配这个结构。所以代码看起来像这样:

typedef auto_ptr<odbc::PreparedStatement> Stmt;

class DbProxy {
public:
  DbProxy(): stmts(new OdbcResources) {}
private:
  void reset() { stmts.reset(); }

  struct OdbcResources {
    Stmt a;
    Stmt b;
    Stmt c;
    // ... about 10 more
  };
  auto_ptr<OdbcResources> stmts;
};

DbProxy的对象不打算复制或复制构造,尽管我没有通过将赋值和copy-ctor设为私有来确保这一点。

你觉得这种方法有什么问题吗?你有其他建议吗?

修改

基于@DeadMG的建议,这是怎么回事:

class DbProxy {
public:
  DbProxy();
private:
  enum Statements { SELECT1, SELECT2, INSERT, LAST };  // never mind the names

  void reset() { for (int i=0; i < LAST; i++) statement[i].reset(); }

  Stmt statements[LAST];
};

5 个答案:

答案 0 :(得分:3)

使用静态大小的数组。

Stmt statements[10];

for(int i = 0; i < sizeof(statements) / sizeof(Stmt); i++)
    statements[i].reset();

答案 1 :(得分:2)

不需要额外的auto_ptr(每个Stmt无论如何都是auto_ptr),如果您在一个班级中收集它们,您可以通过简单的作业重置它们。与数组解决方案不同,您仍然保留其有意义的名称。

请注意,您不能使用未命名的临时(例如stmts = OdbcResources();),因为生成的副本赋值运算符将采用非const引用,因为成员(auto_ptr)不能从非const auto_ptr s。

分配
class DbProxy {
public:
  DbProxy() : stmts() {}
private:
  void reset() { OdbcResources tmp; stmts = tmp; }

  struct OdbcResources {
    Stmt a;
    Stmt b;
    Stmt c;
    // ... about 10 more
  };
  OdbcResources stmts;
};

答案 2 :(得分:1)

这是一个容器的呐喊 - 假设odbc::PreparedStatement是可复制的,只需在DbProxy

中有一个这样的向量
class DbProxy {
private:
  void reset() { resources.clear(); } // all vanish!

  vector<odbc::PreparedStatement> resources;
};

否则,shared_ptr

typedef shared_ptr<odbc::PreparedStatement> Stmt;
class DbProxy {
private:
  void reset() { resources.clear(); } // all vanish!

  vector<Stmt> resources;
};

答案 3 :(得分:1)

我认为这种方法没有错。 这看起来像是“私人实施”的习惯用语。您可能对details感兴趣。

MY2C

答案 4 :(得分:0)

您可以简单地复制默认副本:

void reset() { *this = DbProxy(); }