diff -r 796b70250470 libinterp/octave-value/ov.cc
--- a/libinterp/octave-value/ov.cc	Sun Nov 21 16:49:58 2021 +0100
+++ b/libinterp/octave-value/ov.cc	Mon Feb 27 12:30:56 2023 -0500
@@ -113,16 +113,8 @@ static bool Voptimize_permutation_matrix
 
 static bool Voptimize_range = true;
 
-// FIXME
-
-// Octave's value type.
-
-octave_base_value *
-octave_value::nil_rep ()
-{
-  static octave_base_value nr;
-  return &nr;
-}
+// The object that is the nil representation of a octave_value
+octave_value::octave_nil octave_value::nil_ov_base;
 
 std::string
 octave_value::unary_op_as_string (unary_op op)
diff -r 796b70250470 libinterp/octave-value/ov.h
--- a/libinterp/octave-value/ov.h	Sun Nov 21 16:49:58 2021 +0100
+++ b/libinterp/octave-value/ov.h	Mon Feb 27 12:30:56 2023 -0500
@@ -337,7 +337,7 @@ public:
     // operator, rep may be a nullptr here.  We should only need to
     // protect the move assignment operator in a similar way.
 
-    if (m_rep && --m_rep->m_count == 0 && m_rep != nil_rep ())
+    if (m_rep && --m_rep->m_count == 0)
       delete m_rep;
   }
 
@@ -347,7 +347,7 @@ public:
       {
         octave_base_value *r = m_rep->unique_clone ();
 
-        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0)
           delete m_rep;
 
         m_rep = r;
@@ -363,7 +363,7 @@ public:
       {
         octave_base_value *r = m_rep->unique_clone ();
 
-        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0)
           delete m_rep;
 
         m_rep = r;
@@ -382,7 +382,7 @@ public:
   {
     if (m_rep != a.m_rep)
       {
-        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0)
           delete m_rep;
 
         m_rep = a.m_rep;
@@ -400,7 +400,7 @@ public:
 
     if (this != &a)
       {
-        if (m_rep && --m_rep->m_count == 0 && m_rep != nil_rep ())
+        if (m_rep && --m_rep->m_count == 0)
           delete m_rep;
 
         m_rep = a.m_rep;
@@ -1520,7 +1520,25 @@ protected:
 
 private:
 
-  static OCTINTERP_API octave_base_value * nil_rep ();
+  // Special class to make a octave_base_value that will never have a zero count
+  // so that we can create a static octave_base_value and not call delete on it
+  // in the octave_value dtors, move constructors etc that check count for
+  // whether to call delete or not.
+  class octave_nil : public octave_base_value
+  {
+    public:
+    octave_nil ()
+    {
+      m_count++;
+    }
+  };
+
+  static OCTINTERP_API octave_nil nil_ov_base;
+
+  static OCTINTERP_API octave_base_value *nil_rep (void)
+  {
+     return &nil_ov_base;
+  }
 
   OCTINTERP_API assign_op unary_op_to_assign_op (unary_op op);
 
diff -r 796b70250470 liboctave/array/idx-vector.cc
--- a/liboctave/array/idx-vector.cc	Sun Nov 21 16:49:58 2021 +0100
+++ b/liboctave/array/idx-vector.cc	Mon Feb 27 12:30:56 2023 -0500
@@ -55,11 +55,8 @@ OCTAVE_NORETURN static void err_index_ou
     ("internal error: idx_vector index out of range");
 }
 
-idx_vector::idx_vector_rep *idx_vector::nil_rep ()
-{
-  static idx_vector_rep ivr;
-  return &ivr;
-}
+// Object for nil representation of idx_vector_rep
+idx_vector::idx_vector_rep_nil idx_vector::nil_idx_vector_rep;
 
 Array<octave_idx_type> idx_vector::idx_base_rep::as_array ()
 {
diff -r 796b70250470 liboctave/array/idx-vector.h
--- a/liboctave/array/idx-vector.h	Sun Nov 21 16:49:58 2021 +0100
+++ b/liboctave/array/idx-vector.h	Mon Feb 27 12:30:56 2023 -0500
@@ -421,10 +421,6 @@ private:
 
   idx_vector (idx_base_rep *r) : m_rep (r) { }
 
-  // The shared empty vector representation (for fast default
-  // constructor).
-  static OCTAVE_API idx_vector_rep * nil_rep ();
-
 public:
 
   // Fast empty constructor.
@@ -498,7 +494,7 @@ public:
 
   ~idx_vector ()
   {
-    if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+    if (--m_rep->m_count == 0)
       delete m_rep;
   }
 
@@ -506,7 +502,7 @@ public:
   {
     if (this != &a)
       {
-        if (--m_rep->m_count == 0 && m_rep != nil_rep ())
+        if (--m_rep->m_count == 0)
           delete m_rep;
 
         m_rep = a.m_rep;
@@ -1010,6 +1006,28 @@ public:
 
 private:
 
+  // Special class to make a idx_vector_rep that will never have a zero count
+  // so that we can create a static idx_vector_rep and not call delete on it
+  // in dtors, move constructors etc. See idx_vector::nil_rep
+  class idx_vector_rep_nil : public idx_vector_rep
+  {
+    public:
+    idx_vector_rep_nil ()
+    {
+      m_count++;
+    }
+  };
+
+  // Object for nil representation of idx_vector_rep
+  static OCTAVE_API idx_vector_rep_nil nil_idx_vector_rep;
+
+  // The shared empty vector representation (for fast default
+  // constructor).
+  static OCTAVE_API idx_vector_rep *nil_rep (void)
+  {
+    return &nil_idx_vector_rep;
+  }
+
   idx_base_rep *m_rep;
 
 };
