Search code examples
c++constructordefault-arguments

Initialize member reference with default value


I have a class with a std::vector const& member which shall be set through the constructor. However, it should also be possible to omit this parameter in the constructor and let the member be initialized by a default value.

Example Code:

class MyClass {
public:
  MyClass(int a, const std::vector<int> &v = {42,42,42}) : vec(v){}

  const std::vector<int> &vec;
};

int main(void) {

  std::vector<int> a{1,2,3};

  MyClass c1(1,a);              // c1.vec = 1,2,3
  MyClass c2(1);                // c2.vec = randomStuff
                                // should actually be 42,42,42
}

If I change the initialization to:

MyClass(int a, const std::vector<int> &v = *(new std::vector<int>{42,42,42})) : vec(v){}

Everything works fine since the temporary vector is not deleted when going out of scope. However, this doesn't feel right and look memory leaky. Is there a saner way to achieve the expected behavior?


Solution

  • You can define the default argument as a static data member of your class:

    class MyClass {
     public:
      MyClass(int a, const std::vector<int> &v = defaultVec) : vec(v){}
    
      const std::vector<int> &vec;
    
     private:
      static const std::vector<int> defaultVec;
    };
    
    const std::vector<int> MyClass:defaultVec{42, 42, 42};
    

    To keep the class header-only, you can also use a static variable in a static member function instead:

    class MyClass {
     public:
      MyClass(int a, const std::vector<int> &v = defaultVec()) : vec(v){}
    
      const std::vector<int> &vec;
    
     private:
      static const std::vector<int>& defaultVec()
      {
       static const std::vector<int> v {42, 42, 42};
       return v;
      }
    };
    

    Note that either way, the vector used as the default argument has to have static storage duration, so that it remains valid after the constructor finishes running.