Search code examples
c++memory-managementsmart-pointersauto-ptr

how to reset a large number of class members at once, not in a destructor?


I have a class containing many members of a simple class type. More importantly, their number is growing as I go on with the development.

I need to be able to reset them all at once, and I'd like to do it without copy-pasting them. The code currently looks like:

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.
}

Obviously I don't like having to add every new member to the reset() function (just had a seg. fault for forgetting one).

What I intend to do is to collect them all into a structure and to allocate this structure under auto_ptr. So the code would look like this:

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;
};

Objects of DbProxy are not intended to be copied or copy-constructed, although I didn't bother to ensure this by making the assignment and copy-ctor private.

Do you see any problem with this approach? Do you have other suggestions?

EDIT

based on @DeadMG suggestion, what about this:

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];
};

Solution

  • There's no need for the extra auto_ptr (each Stmt being an auto_ptr anyway), if you collect them in a single class you can reset them with a simple assignment. Unlike an array solution you still preserve their meaningful names.

    Note that you can't use an unnamed temporary (e.g. stmts = OdbcResources();) as the generated copy assignment operator will take a non-const reference as the members (auto_ptr) cannot be assigned from non-const auto_ptrs.

    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;
    };