Commit 73ca936a for tesseract
commit 73ca936aeaa50d283ad696a984a3674c34df5c4c
Author: Stefan Weil <sw@weilnetz.de>
Date: Sat Aug 15 20:09:40 2026 +0200
Add move constructors and move assignment operators
Fix CID 1402759 (Missing move assignment operator) for GENERIC_2D_ARRAY.
Fix CID 1362723 (Missing move assignment operator) for QSPLINE.
Fix CID 1362725 (Missing move assignment operator) for BLOB_CHOICE.
Additionally add missing move operations for WERD_CHOICE which has
the same rule of five violation.
All these classes declare copy constructors, assignment operators and
destructors, so their implicit move constructors and move assignment
operators are not generated. Now they are declared and defined explicitly.
Move operations leave the moved-from object in a valid empty state.
Assisted-by: OpenCode / big-pickle (opencode)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
diff --git a/src/ccstruct/matrix.h b/src/ccstruct/matrix.h
index 84f49c18..dba89eda 100644
--- a/src/ccstruct/matrix.h
+++ b/src/ccstruct/matrix.h
@@ -75,6 +75,15 @@ public:
: array_(nullptr), empty_(static_cast<T>(0)), dim1_(0), dim2_(0), size_allocated_(0) {
*this = src;
}
+ GENERIC_2D_ARRAY(GENERIC_2D_ARRAY<T> &&src) noexcept
+ : array_(src.array_), empty_(src.empty_), dim1_(src.dim1_), dim2_(src.dim2_),
+ size_allocated_(src.size_allocated_) {
+ src.array_ = nullptr;
+ src.empty_ = static_cast<T>(0);
+ src.dim1_ = 0;
+ src.dim2_ = 0;
+ src.size_allocated_ = 0;
+ }
virtual ~GENERIC_2D_ARRAY() {
delete[] array_;
}
@@ -86,6 +95,21 @@ public:
memcpy(array_, src.array_, size * sizeof(array_[0]));
}
}
+ void operator=(GENERIC_2D_ARRAY<T> &&src) noexcept {
+ if (this != &src) {
+ delete[] array_;
+ array_ = src.array_;
+ empty_ = src.empty_;
+ dim1_ = src.dim1_;
+ dim2_ = src.dim2_;
+ size_allocated_ = src.size_allocated_;
+ src.array_ = nullptr;
+ src.empty_ = static_cast<T>(0);
+ src.dim1_ = 0;
+ src.dim2_ = 0;
+ src.size_allocated_ = 0;
+ }
+ }
// Reallocates the array to the given size. Does not keep old data, but does
// not initialize the array either.
diff --git a/src/ccstruct/quspline.cpp b/src/ccstruct/quspline.cpp
index 8036dd08..6b341f56 100644
--- a/src/ccstruct/quspline.cpp
+++ b/src/ccstruct/quspline.cpp
@@ -141,6 +141,16 @@ QSPLINE::QSPLINE( // constructor
*this = src;
}
+QSPLINE::QSPLINE( // move constructor
+ QSPLINE &&src) noexcept {
+ segments = src.segments;
+ xcoords = src.xcoords;
+ quadratics = src.quadratics;
+ src.segments = 0;
+ src.xcoords = nullptr;
+ src.quadratics = nullptr;
+}
+
/**********************************************************************
* QSPLINE::~QSPLINE
*
@@ -171,6 +181,22 @@ QSPLINE &QSPLINE::operator=( // assignment
return *this;
}
+QSPLINE &QSPLINE::operator=( // move assignment
+ QSPLINE &&source) noexcept {
+ if (this != &source) {
+ delete[] xcoords;
+ delete[] quadratics;
+
+ segments = source.segments;
+ xcoords = source.xcoords;
+ quadratics = source.quadratics;
+ source.segments = 0;
+ source.xcoords = nullptr;
+ source.quadratics = nullptr;
+ }
+ return *this;
+}
+
/**********************************************************************
* QSPLINE::step
*
diff --git a/src/ccstruct/quspline.h b/src/ccstruct/quspline.h
index ea27ede5..1a98b8e3 100644
--- a/src/ccstruct/quspline.h
+++ b/src/ccstruct/quspline.h
@@ -46,6 +46,7 @@ public:
}
QSPLINE( // copy constructor
const QSPLINE &src);
+ QSPLINE(QSPLINE &&src) noexcept; // move constructor
QSPLINE( // constructor
int32_t count, // number of segments
int32_t *xstarts, // segment starts
@@ -85,6 +86,7 @@ public:
void plot(Image pix) const;
QSPLINE &operator=(const QSPLINE &source); // from this
+ QSPLINE &operator=(QSPLINE &&source) noexcept;
private:
int32_t spline_index( // binary search
diff --git a/src/ccstruct/ratngs.h b/src/ccstruct/ratngs.h
index cf18a95e..2d3c2740 100644
--- a/src/ccstruct/ratngs.h
+++ b/src/ccstruct/ratngs.h
@@ -76,6 +76,7 @@ public:
float yshift, // the larger of y shift (top or bottom)
BlobChoiceClassifier c); // adapted match or other
BLOB_CHOICE(const BLOB_CHOICE &other);
+ BLOB_CHOICE(BLOB_CHOICE &&other) noexcept = default;
~BLOB_CHOICE() = default;
UNICHAR_ID unichar_id() const {
@@ -192,6 +193,8 @@ public:
private:
// Copy assignment operator.
BLOB_CHOICE &operator=(const BLOB_CHOICE &other);
+ // Move assignment operator.
+ BLOB_CHOICE &operator=(BLOB_CHOICE &&other) noexcept = default;
UNICHAR_ID unichar_id_; // unichar id
#ifndef DISABLED_LEGACY_ENGINE
@@ -276,6 +279,7 @@ public:
this->init(word.length());
this->operator=(word);
}
+ WERD_CHOICE(WERD_CHOICE &&word) noexcept = default;
~WERD_CHOICE();
const UNICHARSET *unicharset() const {
@@ -573,6 +577,7 @@ public:
const WERD_CHOICE &second); // second on first
WERD_CHOICE &operator=(const WERD_CHOICE &source);
+ WERD_CHOICE &operator=(WERD_CHOICE &&source) noexcept = default;
private:
const UNICHARSET *unicharset_;