From d30c19fee67e7ab22a7eff3180da1f20cc054197 Mon Sep 17 00:00:00 2001 From: Julien STAUB Date: Tue, 4 Aug 2026 16:53:40 +0200 Subject: [PATCH 1/5] fix some uninitialized fields --- wavefront.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wavefront.cpp b/wavefront.cpp index b62cf757..ace0efaa 100644 --- a/wavefront.cpp +++ b/wavefront.cpp @@ -49,6 +49,7 @@ wavefront::wavefront( const wavefront &wf): GBSmoothingValue(wf.GBSmoothingValue), m_origin(wf.m_origin), m_manuallyInverted(wf.m_manuallyInverted), + name(wf.name), lambda(wf.lambda), m_outside(wf.m_outside), m_inside(wf.m_inside), @@ -58,6 +59,8 @@ wavefront::wavefront( const wavefront &wf): max(wf.max), std(wf.std), mean(wf.mean), - dirtyZerns(wf.dirtyZerns) + dirtyZerns(wf.dirtyZerns), + regions(wf.regions), + regions_have_been_expanded(wf.regions_have_been_expanded) {} From 938976cb2538ceec7bc699f06655a56dc44b573b Mon Sep 17 00:00:00 2001 From: Julien STAUB Date: Tue, 4 Aug 2026 16:55:03 +0200 Subject: [PATCH 2/5] use default destructor as it works as well --- wavefront.cpp | 11 ----------- wavefront.h | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/wavefront.cpp b/wavefront.cpp index ace0efaa..85deab39 100644 --- a/wavefront.cpp +++ b/wavefront.cpp @@ -22,17 +22,6 @@ wavefront::wavefront(): { } -wavefront::~wavefront() -{ - - data.release(); - mask.release(); - workData.release(); - workMask.release(); - InputZerns.clear(); - nulledData.release(); - -} wavefront::wavefront( const wavefront &wf): data(wf.data.clone()), nulledData(wf.nulledData.clone()), diff --git a/wavefront.h b/wavefront.h index e35c088a..5b3c8cdf 100644 --- a/wavefront.h +++ b/wavefront.h @@ -36,7 +36,7 @@ class wavefront { public: wavefront(); - ~wavefront(); + ~wavefront() = default; wavefront( const wavefront &wf); // copy constructor doing deep copy of cv::Mat wavefront( wavefront && ) = delete; // move constructor, deleted because unused wavefront& operator=( const wavefront & ) = default; // copy operator not doing deep copy of cv::mat From a612200808a4079405ce760fe64c044698195eeb Mon Sep 17 00:00:00 2001 From: Julien STAUB Date: Tue, 1 Sep 2026 14:59:43 +0200 Subject: [PATCH 3/5] this is only place where copy constructor is actually used --- surfacemanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/surfacemanager.cpp b/surfacemanager.cpp index 759a1393..f8d8b12c 100644 --- a/surfacemanager.cpp +++ b/surfacemanager.cpp @@ -2415,7 +2415,7 @@ textres SurfaceManager::Phase2(QList list, QList inp ContourPlot *cp = new ContourPlot(); cp->m_zRangeMode = "Fractions of Wave"; cp->contourWaveRangeChanged(inputs[0]->std* 3); - wavefront * wf = new wavefront(*inputs[i]); + wavefront * wf = new wavefront(*inputs[i]); //TODO 1/2 sole usage of copy constructor wf->data = wf->workData = standwfs[i]; @@ -2460,7 +2460,7 @@ textres SurfaceManager::Phase2(QList list, QList inp //display average of all stand zernwavefronts - wavefront * wf2 = new wavefront(*inputs[0]); + wavefront * wf2 = new wavefront(*inputs[0]); //TODO 2/2 sole usage of copy constructor wf2->data = wf2->workData = standavgZernMat ; cv::resize(inputs[0]->mask,wf2->mask, cv::Size(wf2->data.cols, wf2->data.rows)); wf2->workMask = wf2->mask; From 9a8ce623a19fa8ce96f610389fcf878c03f52f19 Mon Sep 17 00:00:00 2001 From: Julien STAUB Date: Wed, 2 Sep 2026 09:25:11 +0200 Subject: [PATCH 4/5] replace copy constructor and operator with explicit function names --- surfacemanager.cpp | 24 ++++------ wavefront.cpp | 101 ++++++++++++++++++++++++++++------------ wavefront.h | 11 +++-- zernikesmoothingdlg.cpp | 4 +- 4 files changed, 89 insertions(+), 51 deletions(-) diff --git a/surfacemanager.cpp b/surfacemanager.cpp index f8d8b12c..a78c3ec8 100644 --- a/surfacemanager.cpp +++ b/surfacemanager.cpp @@ -1821,7 +1821,7 @@ void SurfaceManager::average(QList wfList){ wavefront *wf = new wavefront(); - *wf = *wfList[sizes[maxkey][0]];// copy in all the parameters (e.g. m_inside, lambda, diameter) from first wavefront to average + *wf = wfList[sizes[maxkey][0]]->copyShallow(); wf->data = sum.clone(); wf->mask = mask; wf->workMask = mask.clone(); @@ -1918,8 +1918,7 @@ void SurfaceManager::rotateThese(double angle, QList list){ wavefront *oldWf = m_wavefronts[list[i]]; QStringList l = oldWf->name.split('.'); QString newName = QString("%1_%2%3.wft").arg(l[0]).arg((angle >= 0) ? "CW":"CCW").arg(fabs(angle), 5, 'f', 1, QLatin1Char('0')); // clazy:exclude=qstring-arg - wavefront *wf = new wavefront(); - *wf = *oldWf; // copy everything to new wavefront including basic things like diameter,wavelength,origin + wavefront *wf = new wavefront(oldWf->copyShallow()); //emit nameChanged(wf->name, newName); wf->name = newName; @@ -1990,8 +1989,7 @@ void SurfaceManager::subtract(wavefront *wf1, wavefront *wf2, bool use_null){ cv::Mat result = wf1->data - resize; //result.copyTo(masked, mask); - wavefront *resultwf = new wavefront; - *resultwf = *wf1; + wavefront *resultwf = new wavefront(wf1->copyShallow()); resultwf->data = result.clone(); resultwf->mask = mask.clone(); resultwf->workMask = mask.clone(); @@ -2415,7 +2413,7 @@ textres SurfaceManager::Phase2(QList list, QList inp ContourPlot *cp = new ContourPlot(); cp->m_zRangeMode = "Fractions of Wave"; cp->contourWaveRangeChanged(inputs[0]->std* 3); - wavefront * wf = new wavefront(*inputs[i]); //TODO 1/2 sole usage of copy constructor + wavefront * wf = new wavefront(inputs[i]->copyDeep()); wf->data = wf->workData = standwfs[i]; @@ -2460,7 +2458,7 @@ textres SurfaceManager::Phase2(QList list, QList inp //display average of all stand zernwavefronts - wavefront * wf2 = new wavefront(*inputs[0]); //TODO 2/2 sole usage of copy constructor + wavefront * wf2 = new wavefront(inputs[0]->copyDeep()); wf2->data = wf2->workData = standavgZernMat ; cv::resize(inputs[0]->mask,wf2->mask, cv::Size(wf2->data.cols, wf2->data.rows)); wf2->workMask = wf2->mask; @@ -3333,8 +3331,7 @@ void SurfaceManager::memoryLow(){ okToContinue = resp; } void SurfaceManager::resize( wavefront *wf, int size){ - wavefront *nwf = new wavefront(); - *nwf = *wf; + wavefront *nwf = new wavefront(wf->copyShallow()); nwf->dirtyZerns = true; cv::Mat newData; cv::Mat newMask; @@ -3357,8 +3354,7 @@ void SurfaceManager::resize( wavefront *wf, int size){ } void SurfaceManager::changeWavelength( wavefront *wf, double wavelength){ - wavefront *nwf = new wavefront(); - *nwf = *wf; + wavefront *nwf = new wavefront(wf->copyShallow()); nwf->dirtyZerns = true; nwf->data = nwf->data * ( wf->lambda/wavelength); nwf->lambda = wavelength; @@ -3376,8 +3372,7 @@ void SurfaceManager::flipHorizontal( wavefront *wf){ cv::flip(wf->data, newData, 1); cv::flip(wf->mask, newMask, 1); - wavefront *nwf = new wavefront(); - *nwf = *wf; + wavefront *nwf = new wavefront(wf->copyShallow()); nwf->dirtyZerns = true; nwf->m_inside.m_center.rx() = wf->data.cols-1 - wf->m_inside.m_center.x(); nwf->m_outside.m_center.rx() = wf->data.cols-1 - wf->m_outside.m_center.x(); @@ -3401,8 +3396,7 @@ void SurfaceManager::flipVertical( wavefront *wf){ cv::flip(wf->data, newData, 0); cv::flip(wf->mask, newMask, 0); - wavefront *nwf = new wavefront(); - *nwf = *wf; + wavefront *nwf = new wavefront(wf->copyShallow()); nwf->dirtyZerns = true; nwf->m_inside.m_center.rx() = wf->data.cols-1 - wf->m_inside.m_center.x(); nwf->m_outside.m_center.rx() = wf->data.cols-1 - wf->m_outside.m_center.x(); diff --git a/wavefront.cpp b/wavefront.cpp index 85deab39..44805d8f 100644 --- a/wavefront.cpp +++ b/wavefront.cpp @@ -22,34 +22,75 @@ wavefront::wavefront(): { } -wavefront::wavefront( const wavefront &wf): - data(wf.data.clone()), - nulledData(wf.nulledData.clone()), - mask(wf.mask.clone()), - workData(wf.workData.clone()), - workMask(wf.workMask.clone()), - InputZerns(wf.InputZerns), - zernEnablesApplied(wf.zernEnablesApplied), - gaussian_diameter(wf.gaussian_diameter), - gbEnabled(wf.gbEnabled), - gbValue(wf.gbValue), - wasSmoothed(wf.wasSmoothed), - useSANull(wf.useSANull), - GBSmoothingValue(wf.GBSmoothingValue), - m_origin(wf.m_origin), - m_manuallyInverted(wf.m_manuallyInverted), - name(wf.name), - lambda(wf.lambda), - m_outside(wf.m_outside), - m_inside(wf.m_inside), - diameter(wf.diameter), - roc(wf.roc), - min(wf.min), - max(wf.max), - std(wf.std), - mean(wf.mean), - dirtyZerns(wf.dirtyZerns), - regions(wf.regions), - regions_have_been_expanded(wf.regions_have_been_expanded) -{} +wavefront wavefront::copyShallow() const +{ + wavefront out; + + // those are cv::mat objects. `=` operator will not copy the data, but will create a new header pointing to the same data. So it is a shallow copy. + out.data = data; + out.nulledData = nulledData; + out.mask = mask; + out.workData = workData; + out.workMask = workMask; + + out.InputZerns = InputZerns; + out.zernEnablesApplied = zernEnablesApplied; + out.gaussian_diameter = gaussian_diameter; + out.gbEnabled = gbEnabled; + out.gbValue = gbValue; + out.wasSmoothed = wasSmoothed; + out.useSANull = useSANull; + out.GBSmoothingValue = GBSmoothingValue; + out.m_origin = m_origin; + out.m_manuallyInverted = m_manuallyInverted; + out.name = name; + out.lambda = lambda; + out.m_outside = m_outside; + out.m_inside = m_inside; + out.diameter = diameter; + out.roc = roc; + out.min = min; + out.max = max; + out.std = std; + out.mean = mean; + out.dirtyZerns = dirtyZerns; + out.regions = regions; + out.regions_have_been_expanded = regions_have_been_expanded; + return out; +} + +wavefront wavefront::copyDeep() const +{ + wavefront out; + out.data = data.clone(); + out.nulledData = nulledData.clone(); + out.mask = mask.clone(); + out.workData = workData.clone(); + out.workMask = workMask.clone(); + out.InputZerns = InputZerns; + out.zernEnablesApplied = zernEnablesApplied; + out.gaussian_diameter = gaussian_diameter; + out.gbEnabled = gbEnabled; + out.gbValue = gbValue; + out.wasSmoothed = wasSmoothed; + out.useSANull = useSANull; + out.GBSmoothingValue = GBSmoothingValue; + out.m_origin = m_origin; + out.m_manuallyInverted = m_manuallyInverted; + out.name = name; + out.lambda = lambda; + out.m_outside = m_outside; + out.m_inside = m_inside; + out.diameter = diameter; + out.roc = roc; + out.min = min; + out.max = max; + out.std = std; + out.mean = mean; + out.dirtyZerns = dirtyZerns; + out.regions = regions; + out.regions_have_been_expanded = regions_have_been_expanded; + return out; +} + diff --git a/wavefront.h b/wavefront.h index 5b3c8cdf..705c5600 100644 --- a/wavefront.h +++ b/wavefront.h @@ -37,10 +37,13 @@ class wavefront public: wavefront(); ~wavefront() = default; - wavefront( const wavefront &wf); // copy constructor doing deep copy of cv::Mat - wavefront( wavefront && ) = delete; // move constructor, deleted because unused - wavefront& operator=( const wavefront & ) = default; // copy operator not doing deep copy of cv::mat - wavefront& operator=(wavefront &&) = delete; // move operator, deleted because unused + wavefront(const wavefront&) = delete; + wavefront(wavefront&&) noexcept = default; + wavefront& operator=(const wavefront&) = delete; + wavefront& operator=(wavefront&&) noexcept = default; + + wavefront copyShallow() const; + wavefront copyDeep() const; cv::Mat_ data; cv::Mat_ nulledData; diff --git a/zernikesmoothingdlg.cpp b/zernikesmoothingdlg.cpp index 80f47aff..961aba07 100644 --- a/zernikesmoothingdlg.cpp +++ b/zernikesmoothingdlg.cpp @@ -12,7 +12,7 @@ ZernikeSmoothingDlg::ZernikeSmoothingDlg(wavefront &wf, QWidget *parent) : p_wf = &wf; m_zp = new zernikeProcess; - m_wf = wf; + m_wf = wf.copyShallow(); theZerns = wf.InputZerns; m_noOfTerms = m_zp->getNumberOfTerms(); m_zernEnables = std::vector(m_noOfTerms); @@ -115,7 +115,7 @@ cv::Mat makeSurfaceFromZerns(int width, zernikeProcess &zp, std::vector void ZernikeSmoothingDlg::on_createWaveFront_clicked() { QApplication::setOverrideCursor(Qt::WaitCursor); - m_wf = *p_wf; + m_wf = p_wf->copyShallow(); if (!ui->useCurrentZernySet->isChecked()){ std::vector tzerns = m_zp->ZernFitWavefront(m_wf); if (tzerns.size() == 0){ From d2cd734bc68c66ee133e6637114a79018c492aae Mon Sep 17 00:00:00 2001 From: Julien Staub Date: Wed, 2 Sep 2026 21:28:09 +0200 Subject: [PATCH 5/5] use default for copy constructor and operator (no clone, it's shallow copy) --- surfacemanager.cpp | 26 +++++++++----- wavefront.cpp | 76 ++++------------------------------------- wavefront.h | 12 +++---- zernikesmoothingdlg.cpp | 4 +-- 4 files changed, 30 insertions(+), 88 deletions(-) diff --git a/surfacemanager.cpp b/surfacemanager.cpp index a78c3ec8..bad80138 100644 --- a/surfacemanager.cpp +++ b/surfacemanager.cpp @@ -1821,7 +1821,7 @@ void SurfaceManager::average(QList wfList){ wavefront *wf = new wavefront(); - *wf = wfList[sizes[maxkey][0]]->copyShallow(); + *wf = *wfList[sizes[maxkey][0]];// copy in all the parameters (e.g. m_inside, lambda, diameter) from first wavefront to average wf->data = sum.clone(); wf->mask = mask; wf->workMask = mask.clone(); @@ -1918,7 +1918,8 @@ void SurfaceManager::rotateThese(double angle, QList list){ wavefront *oldWf = m_wavefronts[list[i]]; QStringList l = oldWf->name.split('.'); QString newName = QString("%1_%2%3.wft").arg(l[0]).arg((angle >= 0) ? "CW":"CCW").arg(fabs(angle), 5, 'f', 1, QLatin1Char('0')); // clazy:exclude=qstring-arg - wavefront *wf = new wavefront(oldWf->copyShallow()); + wavefront *wf = new wavefront(); + *wf = *oldWf; // copy everything to new wavefront including basic things like diameter,wavelength,origin //emit nameChanged(wf->name, newName); wf->name = newName; @@ -1989,7 +1990,8 @@ void SurfaceManager::subtract(wavefront *wf1, wavefront *wf2, bool use_null){ cv::Mat result = wf1->data - resize; //result.copyTo(masked, mask); - wavefront *resultwf = new wavefront(wf1->copyShallow()); + wavefront *resultwf = new wavefront; + *resultwf = *wf1; resultwf->data = result.clone(); resultwf->mask = mask.clone(); resultwf->workMask = mask.clone(); @@ -2413,7 +2415,8 @@ textres SurfaceManager::Phase2(QList list, QList inp ContourPlot *cp = new ContourPlot(); cp->m_zRangeMode = "Fractions of Wave"; cp->contourWaveRangeChanged(inputs[0]->std* 3); - wavefront * wf = new wavefront(inputs[i]->copyDeep()); + wavefront * wf = new wavefront(*inputs[i]); + wf->cloneMatricesFrom(*inputs[i]); wf->data = wf->workData = standwfs[i]; @@ -2458,7 +2461,8 @@ textres SurfaceManager::Phase2(QList list, QList inp //display average of all stand zernwavefronts - wavefront * wf2 = new wavefront(inputs[0]->copyDeep()); + wavefront * wf2 = new wavefront(*inputs[0]); + wf2->cloneMatricesFrom(*inputs[0]); wf2->data = wf2->workData = standavgZernMat ; cv::resize(inputs[0]->mask,wf2->mask, cv::Size(wf2->data.cols, wf2->data.rows)); wf2->workMask = wf2->mask; @@ -3331,7 +3335,8 @@ void SurfaceManager::memoryLow(){ okToContinue = resp; } void SurfaceManager::resize( wavefront *wf, int size){ - wavefront *nwf = new wavefront(wf->copyShallow()); + wavefront *nwf = new wavefront(); + *nwf = *wf; nwf->dirtyZerns = true; cv::Mat newData; cv::Mat newMask; @@ -3354,7 +3359,8 @@ void SurfaceManager::resize( wavefront *wf, int size){ } void SurfaceManager::changeWavelength( wavefront *wf, double wavelength){ - wavefront *nwf = new wavefront(wf->copyShallow()); + wavefront *nwf = new wavefront(); + *nwf = *wf; nwf->dirtyZerns = true; nwf->data = nwf->data * ( wf->lambda/wavelength); nwf->lambda = wavelength; @@ -3372,7 +3378,8 @@ void SurfaceManager::flipHorizontal( wavefront *wf){ cv::flip(wf->data, newData, 1); cv::flip(wf->mask, newMask, 1); - wavefront *nwf = new wavefront(wf->copyShallow()); + wavefront *nwf = new wavefront(); + *nwf = *wf; nwf->dirtyZerns = true; nwf->m_inside.m_center.rx() = wf->data.cols-1 - wf->m_inside.m_center.x(); nwf->m_outside.m_center.rx() = wf->data.cols-1 - wf->m_outside.m_center.x(); @@ -3396,7 +3403,8 @@ void SurfaceManager::flipVertical( wavefront *wf){ cv::flip(wf->data, newData, 0); cv::flip(wf->mask, newMask, 0); - wavefront *nwf = new wavefront(wf->copyShallow()); + wavefront *nwf = new wavefront(); + *nwf = *wf; nwf->dirtyZerns = true; nwf->m_inside.m_center.rx() = wf->data.cols-1 - wf->m_inside.m_center.x(); nwf->m_outside.m_center.rx() = wf->data.cols-1 - wf->m_outside.m_center.x(); diff --git a/wavefront.cpp b/wavefront.cpp index 44805d8f..361e9577 100644 --- a/wavefront.cpp +++ b/wavefront.cpp @@ -22,75 +22,11 @@ wavefront::wavefront(): { } -wavefront wavefront::copyShallow() const +void wavefront::cloneMatricesFrom(const wavefront &wf) { - wavefront out; - - // those are cv::mat objects. `=` operator will not copy the data, but will create a new header pointing to the same data. So it is a shallow copy. - out.data = data; - out.nulledData = nulledData; - out.mask = mask; - out.workData = workData; - out.workMask = workMask; - - out.InputZerns = InputZerns; - out.zernEnablesApplied = zernEnablesApplied; - out.gaussian_diameter = gaussian_diameter; - out.gbEnabled = gbEnabled; - out.gbValue = gbValue; - out.wasSmoothed = wasSmoothed; - out.useSANull = useSANull; - out.GBSmoothingValue = GBSmoothingValue; - out.m_origin = m_origin; - out.m_manuallyInverted = m_manuallyInverted; - out.name = name; - out.lambda = lambda; - out.m_outside = m_outside; - out.m_inside = m_inside; - out.diameter = diameter; - out.roc = roc; - out.min = min; - out.max = max; - out.std = std; - out.mean = mean; - out.dirtyZerns = dirtyZerns; - out.regions = regions; - out.regions_have_been_expanded = regions_have_been_expanded; - return out; -} - -wavefront wavefront::copyDeep() const -{ - wavefront out; - out.data = data.clone(); - out.nulledData = nulledData.clone(); - out.mask = mask.clone(); - out.workData = workData.clone(); - out.workMask = workMask.clone(); - out.InputZerns = InputZerns; - out.zernEnablesApplied = zernEnablesApplied; - out.gaussian_diameter = gaussian_diameter; - out.gbEnabled = gbEnabled; - out.gbValue = gbValue; - out.wasSmoothed = wasSmoothed; - out.useSANull = useSANull; - out.GBSmoothingValue = GBSmoothingValue; - out.m_origin = m_origin; - out.m_manuallyInverted = m_manuallyInverted; - out.name = name; - out.lambda = lambda; - out.m_outside = m_outside; - out.m_inside = m_inside; - out.diameter = diameter; - out.roc = roc; - out.min = min; - out.max = max; - out.std = std; - out.mean = mean; - out.dirtyZerns = dirtyZerns; - out.regions = regions; - out.regions_have_been_expanded = regions_have_been_expanded; - return out; + data = wf.data.clone(); + nulledData = wf.nulledData.clone(); + mask = wf.mask.clone(); + workData = wf.workData.clone(); + workMask = wf.workMask.clone(); } - - diff --git a/wavefront.h b/wavefront.h index 705c5600..489c4797 100644 --- a/wavefront.h +++ b/wavefront.h @@ -37,13 +37,11 @@ class wavefront public: wavefront(); ~wavefront() = default; - wavefront(const wavefront&) = delete; - wavefront(wavefront&&) noexcept = default; - wavefront& operator=(const wavefront&) = delete; - wavefront& operator=(wavefront&&) noexcept = default; - - wavefront copyShallow() const; - wavefront copyDeep() const; + wavefront( const wavefront &wf) = default; + wavefront( wavefront && ) = default; + wavefront& operator=( const wavefront & ) = default; + wavefront& operator=(wavefront &&) = default; + void cloneMatricesFrom(const wavefront &wf); cv::Mat_ data; cv::Mat_ nulledData; diff --git a/zernikesmoothingdlg.cpp b/zernikesmoothingdlg.cpp index 961aba07..80f47aff 100644 --- a/zernikesmoothingdlg.cpp +++ b/zernikesmoothingdlg.cpp @@ -12,7 +12,7 @@ ZernikeSmoothingDlg::ZernikeSmoothingDlg(wavefront &wf, QWidget *parent) : p_wf = &wf; m_zp = new zernikeProcess; - m_wf = wf.copyShallow(); + m_wf = wf; theZerns = wf.InputZerns; m_noOfTerms = m_zp->getNumberOfTerms(); m_zernEnables = std::vector(m_noOfTerms); @@ -115,7 +115,7 @@ cv::Mat makeSurfaceFromZerns(int width, zernikeProcess &zp, std::vector void ZernikeSmoothingDlg::on_createWaveFront_clicked() { QApplication::setOverrideCursor(Qt::WaitCursor); - m_wf = p_wf->copyShallow(); + m_wf = *p_wf; if (!ui->useCurrentZernySet->isChecked()){ std::vector tzerns = m_zp->ZernFitWavefront(m_wf); if (tzerns.size() == 0){