Russell
Russell

Reputation: 4085

C++ idiom for dynamically populating objects and destroying at return

I'm using C++0x.

I have a function call_third_party, that receives a list of A*, converts it to a list of B*, then passes that list of B* into function third_party. After third_party is called, the list of B* is no longer needed.

As the name suggests, I have no control over third_party.

Currently I have something like this.

void call_third_party(const vector<A*>& as) {
    vector<unique_ptr<B>> allocated_bs;
    vector<B*> bs;
    vector<A*>::iterator it;
    for (it = as.begin(); it < as.end(); it++) {
        unique_ptr<B> b(new B(*it));
        allocated_bs.push_back(b);
        bs.push_back(b.get());
    }
    third_party(bs);
}

Just in case this helps. Here are B's constructor and third_party's signature.

void third_party(const vector<B*>& bs);
B(A* a);

Is there a better, idiomatic way to do this?

Upvotes: 0

Views: 211

Answers (4)

Nim
Nim

Reputation: 33645

IMHO, seems a bit much to allocate a second vector just for the pointers - shock horror, why not do it the old fashioned way?

template <typename PtrContainer>
struct auto_delete
{
  ~auto_delete()
  {
    for(auto it = _cont.begin(); it != _cont.end(); ++it)
      delete *it;
  }
  PtrContainer& _cont;
};

void call_third_party(const vector<A*>& as)
{
  std::vector<B*> allocated_bs;
  allocated_bs.reserve(as.size());
  // this will take care of cleanup - irrespective of where the exit point is
  auto_delete<std::vector<B*>> dt = { allocated_bs }; 
  (void)dt;
  for(auto it = as.begin(); it != as.end(); ++it)
    allocated_bs.push_back(new B(*it));
  third_party(allocated_bs);
}

Upvotes: 0

Luc Danton
Luc Danton

Reputation: 35449

Would

// change name to held_b or something?
vector<B> allocated_bs;
// ...
for(...) {
    auto emplaced = allocated_bs.emplace(allocated_bs.end(), *it);
    bs.push_back(&*emplaced);

be possible? I don't see the need for dynamic allocation.

Upvotes: 3

Gene Bushuyev
Gene Bushuyev

Reputation: 5538

void call_third_party(const vector<A*>& as)
{
   std::vector<B> b(as.begin(), as.end());
   std::vector<B*> bp(b.size());
   std::transform(b.begin(), b.end(), bp.begin(), [](B& b) { return &b; });
   third_party(bp);
}

Upvotes: 9

Ben Voigt
Ben Voigt

Reputation: 283733

Boost's ptr_vector might make that a lot simpler.

Upvotes: 0

Related Questions