1

I'm looking for a design pattern which can store vector of pointers and can remove the vector of pointers based on the demand.

This is my existing code path.

### implementation.h

class A {
   A() {}
   private:
     void AggregateMetrics();
     void FlushMetrics();
     X* x_;
     Y* y_;
};

class X {
   public:
       void CreateFiles(vector<B*> *objects, string path);
};

class B {
   B() {
     m_ = 0, n_ = 0;  
   }
   private:
      int m_, n_;
};

### implementation.cpp


void A::A() {
  x_ = new X();
  y_ = new Y();
}

void A::AggregateMetrics() {
}

void A::FlushMetrics () {
    vector<B*> objects;
    x_->CreateFiles(&objects, path);
    // In my new code, we are going to move the above two lines 
    // to AggregateMetrics() and i need to find a way to store 
    // the vector<B*>objects;
    y_->Flush(objects);
    return;
}

void X::CreateFiles(vector<B*> *objects, string path) {
    CHECK(objects.empty());
    for (int i = 0; i < 10; i++) {
        objects->push_back(new B());
    }
}

Here is my new code: ### implementation.h

class A {
   A() {}
   private:
     void AggregateMetrics();
     void FlushMetrics();
     X* x_;
     Y* y_;
};

class X {
   public:
       void CreateFiles(vector<B*> *objects, string path);
};

class B {
   B() {
     m_ = 0, n_ = 0;  
   }
   private:
      int m_, n_;
};

class PointerManager {
   public:
      PointerManager() {}
      void SetPointers(vector<B*>& objects);
      vector<B*> GetPointers();
   private:
      vector<B*>objects_;
};

### implementation.cpp
PointerManager::SetPointers(vector<B*>& objects) {
   objects_ = objects;
}

vector<B*> PointerManager::GetPointers() {
   return objects_;
}

void A::A() {
  x = new X();
  y = new Y();
  mgr_ = new PointerManager();
}

void A::AggregateMetrics() {
    vector<B*> objects;
    x->CreateFiles(&objects, path);
    mgr_->SetPointers(objects);
}

void A::FlushMetrics () {
    auto objects = mgr_->GetPointers();
    y->Flush(objects);
    return;
}

void X::CreateFiles(vector<B*> *objects, string path) {
    CHECK(objects.empty());
    for (;;) {
        objects->push_back(new B());
    }
}

I'm basically creating a new class called PointerManager which can hold these pointers after the creation and can return when needed. What would be the ideal design here? Can you guys suggest a design pattern?

user1159517
  • 5,390
  • 8
  • 30
  • 47

2 Answers2

3

I suggest using smart pointer and store them into a container to avoid any memory leak.

Here's the version of your design using smart pointer

implementation.hpp :

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <cassert>
class B {
    public:
        B() {
            m_ = 0, n_ = 0;
        }
    private:
        int m_, n_;
};
class Y{
    public:
        Y(){}
        ~Y(){}
        void Flush(std::vector<std::unique_ptr<B>>& objects);
};
class X {
    public:
        void CreateFiles(std::vector<std::unique_ptr<B>> &objects, std::string path);
};
class PointerManager {
    public:
        PointerManager() {}
        void InsertPointer(std::unique_ptr<B> &object);
        void SetPointers(std::vector<std::unique_ptr<B>> &objects);
        std::vector<std::unique_ptr<B>> &GetPointers();
    private:
        std::vector<std::unique_ptr<B>> objects_;
};
class A {
    public:
        A();
        void AggregateMetrics();
        void FlushMetrics();
    private:
        X* x_;
        Y* y_;
        PointerManager* mgr_;
};

implementation.cpp

#include "implementation.hpp"

void Y::Flush(std::vector<std::unique_ptr<B>>& objects){
    for(int i =0;i<objects.size();i++){
        objects[i].release();
    }
}

void X::CreateFiles(std::vector<std::unique_ptr<B>> &objects, std::string path) {
    assert(objects.empty());
    for (int i = 0; i < 5;i++) {
        std::cout << "for loop in CreatesFiles " << std::endl;
        objects.emplace_back(new B);
    }
}

void PointerManager::InsertPointer(std::unique_ptr<B> &object) {
    std::cout << "InsertPointer " << std::endl;
    objects_.push_back(std::move(object)); // object now belongs to PointerManager
}

void PointerManager::SetPointers(std::vector<std::unique_ptr<B>> &objects){
    for(int i=0;i<objects.size();i++){
        this->InsertPointer(objects[i]);
    }
}

std::vector<std::unique_ptr<B>>& PointerManager::GetPointers() {
    std::cout << "Get Pointers" << std::endl;
    return objects_;
}

A::A() {
    x_ = new X();
    y_ = new Y();
    mgr_ = new PointerManager();
}

void A::AggregateMetrics() {
    std::cout << "Aggregate Metrics " << std::endl;
    std::string path = ".";
    std::vector<std::unique_ptr<B>> objects;

    x_->CreateFiles(objects, path);
    mgr_->SetPointers(objects);
}

void A::FlushMetrics () {
    std::cout << "Flush Metrics " << std::endl;
    y_->Flush(mgr_->GetPointers());
    return;
}

This run fine with CLANG 3.4.2 and g++ 4.9.3 using -std=c++11 flag.

Clonk
  • 2,025
  • 1
  • 11
  • 26
2

What you are basically asking is: "how do I implement my own memory management using raw pointers?"

And the answer to that is: you don't.

Modern day C++ offers concepts such as smart pointers or unique/shared pointers that take a lot of that "management" burden from the shoulders of your application code.

So the real answer here is: step back, and learn how to use C++ with all the means that are available in 2017; instead of writing code that would have been written like that 15, 20 years ago.

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248