changeset 27352:7335ebd4c798

define some move constructors and assignment operators * Array.h, dim-vector.h, str-vec.h, ov.h: Define move constructors and assignment operators for the Array, dim_vector, string_vector, and octave_value classes. * ovl.h: Use default move constructor and assignment operator.
author John W. Eaton <jwe@octave.org>
date Wed, 21 Aug 2019 16:00:37 -0400
parents 367066c92535
children 8db55255c9d1
files libinterp/octave-value/ov.h libinterp/octave-value/ovl.h liboctave/array/Array.h liboctave/array/dim-vector.h liboctave/util/str-vec.h
diffstat 5 files changed, 109 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov.h	Wed Aug 21 05:49:38 2019 -0400
+++ b/libinterp/octave-value/ov.h	Wed Aug 21 16:00:37 2019 -0400
@@ -302,11 +302,17 @@
   // Copy constructor.
 
   octave_value (const octave_value& a)
+    : rep (a.rep)
   {
-    rep = a.rep;
     rep->count++;
   }
 
+  octave_value (octave_value&& a)
+    : rep (a.rep)
+  {
+    a.rep = nullptr;
+  }
+
   // This should only be called for derived types.
 
   octave_base_value * clone (void) const;
@@ -318,7 +324,11 @@
 
   ~octave_value (void)
   {
-    if (--rep->count == 0)
+    // Because we define a move constructor and a move assignment
+    // operator, rep may be a nullptr here.  We should only need to
+    // protect the move assignment operator in a similar way.
+
+    if (rep && --rep->count == 0)
       delete rep;
   }
 
@@ -367,6 +377,24 @@
     return *this;
   }
 
+  octave_value& operator = (octave_value&& a)
+  {
+    // Because we define a move constructor and a move assignment
+    // operator, rep may be a nullptr here.  We should only need to
+    // protect the destructor in a similar way.
+
+    if (this != &a)
+      {
+        if (rep && --rep->count == 0)
+          delete rep;
+
+        rep = a.rep;
+        a.rep = nullptr;
+      }
+
+    return *this;
+  }
+
   octave_idx_type get_count (void) const { return rep->count; }
 
   octave_base_value::type_conv_info numeric_conversion_function (void) const
--- a/libinterp/octave-value/ovl.h	Wed Aug 21 05:49:38 2019 -0400
+++ b/libinterp/octave-value/ovl.h	Wed Aug 21 16:00:37 2019 -0400
@@ -75,6 +75,8 @@
   octave_value_list (const octave_value_list& obj)
     : m_data (obj.m_data), m_names (obj.m_names) { }
 
+  octave_value_list (octave_value_list&& obj) = default;
+
   // Concatenation constructor.
   octave_value_list (const std::list<octave_value_list>&);
 
@@ -91,6 +93,8 @@
     return *this;
   }
 
+  octave_value_list& operator = (octave_value_list&& obj) = default;
+
   Array<octave_value> array_value (void) const
   {
     Array<octave_value> retval;
--- a/liboctave/array/Array.h	Wed Aug 21 05:49:38 2019 -0400
+++ b/liboctave/array/Array.h	Wed Aug 21 16:00:37 2019 -0400
@@ -300,11 +300,24 @@
     rep->count++;
   }
 
+  Array (Array<T>&& a)
+    : dimensions (std::move (a.dimensions)), rep (a.rep),
+      slice_data (a.slice_data), slice_len (a.slice_len)
+  {
+    a.rep = nullptr;
+    a.slice_data = nullptr;
+    a.slice_len = 0;
+  }
+
 public:
 
   virtual ~Array (void)
   {
-    if (--rep->count == 0)
+    // Because we define a move constructor and a move assignment
+    // operator, rep may be a nullptr here.  We should only need to
+    // protect the move assignment operator in a similar way.
+
+    if (rep && --rep->count == 0)
       delete rep;
   }
 
@@ -326,6 +339,31 @@
     return *this;
   }
 
+  Array<T>& operator = (Array<T>&& a)
+  {
+    if (this != &a)
+      {
+        dimensions = std::move (a.dimensions);
+
+        // Because we define a move constructor and a move assignment
+        // operator, rep may be a nullptr here.  We should only need to
+        // protect the destructor in a similar way.
+
+        if (rep && --rep->count == 0)
+          delete rep;
+
+        rep = a.rep;
+        slice_data = a.slice_data;
+        slice_len = a.slice_len;
+
+        a.rep = nullptr;
+        a.slice_data = nullptr;
+        a.slice_len = 0;
+      }
+
+    return *this;
+  }
+
   void fill (const T& val);
 
   void clear (void);
--- a/liboctave/array/dim-vector.h	Wed Aug 21 05:49:38 2019 -0400
+++ b/liboctave/array/dim-vector.h	Wed Aug 21 16:00:37 2019 -0400
@@ -258,7 +258,9 @@
   dim_vector (const dim_vector& dv) : rep (dv.rep)
   { OCTAVE_ATOMIC_INCREMENT (&(count ())); }
 
-  // FIXME: Should be private, but required by array constructor for jit
+  dim_vector (dim_vector&& dv) : rep (dv.rep) { dv.rep = nullptr; }
+
+// FIXME: Should be private, but required by array constructor for jit
   explicit dim_vector (octave_idx_type *r) : rep (r) { }
 
   static dim_vector alloc (int n)
@@ -280,9 +282,31 @@
     return *this;
   }
 
+  dim_vector& operator = (dim_vector&& dv)
+  {
+    if (&dv != this)
+      {
+        // Because we define a move constructor and a move assignment
+        // operator, rep may be a nullptr here.  We should only need to
+        // protect the destructor in a similar way.
+
+        if (rep && OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+          freerep ();
+
+        rep = dv.rep;
+        dv.rep = nullptr;
+      }
+
+    return *this;
+  }
+
   ~dim_vector (void)
   {
-    if (OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
+    // Because we define a move constructor and a move assignment
+    // operator, rep may be a nullptr here.  We should only need to
+    // protect the move assignment operator in a similar way.
+
+    if (rep && OCTAVE_ATOMIC_DECREMENT (&(count ())) == 0)
       freerep ();
   }
 
--- a/liboctave/util/str-vec.h	Wed Aug 21 05:49:38 2019 -0400
+++ b/liboctave/util/str-vec.h	Wed Aug 21 16:00:37 2019 -0400
@@ -47,6 +47,8 @@
 
   string_vector (const string_vector& s) : m_data (s.m_data) { }
 
+  string_vector (string_vector&& s) : m_data (std::move (s.m_data)) { }
+
   //! Constructor for STL containers of std::string.
   //!
   //! Templated constructor for any template class with std::string as the
@@ -71,6 +73,14 @@
     return *this;
   }
 
+  string_vector& operator = (string_vector&& s)
+  {
+    if (this != &s)
+      m_data = std::move (s.m_data);
+
+    return *this;
+  }
+
   ~string_vector (void) = default;
 
   bool empty (void) const { return numel () == 0; }