c++pimpl-idiom

Constructor and destructor in c++ when using the pimpl idiom


I come from Java that has a different way in handling what's private and has to be hided regarding a class implementation and it also has a garbage collector which means there is no need for a destructor.

I learned the basics of how to implement a class in c++ but I need to better understand how to implement a class, in particular the constructor and destructor, when using the pimpl idiom.

hpp file:

class MyClass{
public:
  MyClass();
  MyClass(std::vector<int>& arr);
  ~MyClass();

 
private:
  struct Impl;
  Impl* pimpl;
};

cpp file:

#include "MyClass.hpp"
using namespace std;


struct MyClass::Impl{
  vector<int> arr;
  int var;
};

I wrote the sample code of a class I need to work on(which means I can't change the way the pimpl idiom is used) using the pimpl idiom and I'm looking for an answer to these questions:

MyClass::MyClass(){}
MyClass::MyClass(vector<int>& arr,int var){}
MyClass::~MyClass(){}

EDIT:

How I would do it:

MyClass::MyClass(): pimpl(new Impl) {}

MyClass::MyClass(vector<int>& arr,int var): pimpl(new Impl) {
  pimpl->arr=arr;
  pimpl->var=var;
}

MyClass::~MyClass(){
  delete pimpl;
}


Solution

  • This is an example of a correct way to implement PIMPL idiom in modern C++:

    foo.hpp

    #pragma once
    
    #include <memory>
    
    class Foo {
    public:
      Foo();
      ~Foo();
    
      Foo(Foo const &) = delete;
      Foo &operator=(Foo const &) = delete;
    
      Foo(Foo &&) noexcept;
      Foo &operator=(Foo &&) noexcept;
    
      void bar();
    
    private:
      class impl;
      std::unique_ptr<impl> pimpl_;
    };
    

    foo.cpp:

    #include "foo.hpp"
    
    #include <iostream>
    
    class Foo::impl {
    public:
      impl() = default;
      ~impl() = default;
    
      impl(impl const &) = default;
      impl &operator=(impl const &) = default;
    
      impl(impl &&) noexcept = default;
      impl &operator=(impl &&) noexcept = default;
    
      void bar() { std::cout << "bar" << std::endl; }
    };
    
    Foo::Foo() : pimpl_(new impl{}) {}
    Foo::~Foo() = default;
    
    Foo::Foo(Foo &&) noexcept = default;
    Foo &Foo::operator=(Foo &&) noexcept = default;
    
    void Foo::bar() { pimpl_->bar(); }
    

    main.cpp:

    #include "foo.hpp"
    
    int main(int argc, char const *argv[]) {
      Foo foo;
      foo.bar();
      return 0;
    }
    

    There are a few words that are to be said: