From bb79801dcf43e99ca11b7d47cbbc88c1a549889a Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Tue, 23 Dec 2025 11:42:45 +0100 Subject: [PATCH 1/2] STYLE: Replace AllocateElements calls within VariableLengthVector It appears unnecessary for VariableLengthVector to replace exceptions from `new T[n]` with ITK exceptions. This commit also simplified the `VariableLengthVector(length)` constructor. --- .../Common/include/itkVariableLengthVector.h | 3 +-- .../include/itkVariableLengthVector.hxx | 27 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Modules/Core/Common/include/itkVariableLengthVector.h b/Modules/Core/Common/include/itkVariableLengthVector.h index 52cea457f7c..ccc658d28c3 100644 --- a/Modules/Core/Common/include/itkVariableLengthVector.h +++ b/Modules/Core/Common/include/itkVariableLengthVector.h @@ -404,11 +404,10 @@ class ITK_TEMPLATE_EXPORT VariableLengthVector */ template VariableLengthVector(const VariableLengthVector & v) - : m_NumElements(v.Size()) + : VariableLengthVector(v.Size()) { if (m_NumElements != 0) { - m_Data = this->AllocateElements(m_NumElements); itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr); for (ElementIdentifier i = 0; i < m_NumElements; ++i) { diff --git a/Modules/Core/Common/include/itkVariableLengthVector.hxx b/Modules/Core/Common/include/itkVariableLengthVector.hxx index 7ea779f5df5..b9666b7862e 100644 --- a/Modules/Core/Common/include/itkVariableLengthVector.hxx +++ b/Modules/Core/Common/include/itkVariableLengthVector.hxx @@ -18,6 +18,7 @@ #ifndef itkVariableLengthVector_hxx #define itkVariableLengthVector_hxx +#include "itkMakeUniqueForOverwrite.h" #include "itkNumericTraitsVariableLengthVectorPixel.h" #include "itkMath.h" #include @@ -28,9 +29,9 @@ namespace itk template VariableLengthVector::VariableLengthVector(unsigned int length) - : m_Data(nullptr) + : m_Data(new TValue[length]) + , m_NumElements(length) { - Reserve(length); // postcondition(s) itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr); } @@ -58,11 +59,10 @@ VariableLengthVector::VariableLengthVector(const ValueType * datain, uns template VariableLengthVector::VariableLengthVector(const VariableLengthVector & v) - : m_NumElements(v.Size()) + : VariableLengthVector(v.m_NumElements) { if (m_NumElements != 0) { - m_Data = this->AllocateElements(m_NumElements); itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr); itkAssertInDebugAndIgnoreInReleaseMacro(v.m_Data != nullptr); std::copy_n(&v.m_Data[0], m_NumElements, &this->m_Data[0]); @@ -131,10 +131,9 @@ template ::VariableLengthVector( const VariableLengthVectorExpression & rhs) - : m_NumElements(rhs.Size()) + : VariableLengthVector(rhs.Size()) { - m_Data = this->AllocateElements(m_NumElements); - // allocate Elements post-condition + // VariableLengthVector(length) post-condition itkAssertInDebugAndIgnoreInReleaseMacro(m_Data != nullptr); for (ElementIdentifier i = 0; i < m_NumElements; ++i) { @@ -176,23 +175,23 @@ VariableLengthVector::Reserve(ElementIdentifier size) { if (size > m_NumElements) { - TValue * temp = this->AllocateElements(size); + auto temp = make_unique_for_overwrite(size); itkAssertInDebugAndIgnoreInReleaseMacro(temp); itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == 0 || (m_NumElements > 0 && m_Data != nullptr)); // only copy the portion of the data used in the old buffer - std::copy_n(m_Data, m_NumElements, temp); + std::copy_n(m_Data, m_NumElements, temp.get()); if (m_LetArrayManageMemory) { delete[] m_Data; } - m_Data = temp; + m_Data = temp.release(); m_LetArrayManageMemory = true; m_NumElements = size; } } else { - m_Data = this->AllocateElements(size); + m_Data = new TValue[size]; m_NumElements = size; m_LetArrayManageMemory = true; } @@ -273,16 +272,16 @@ VariableLengthVector::SetSize(unsigned int sz, TReallocatePolicy realloc if (reallocatePolicy(sz, m_NumElements) || !m_LetArrayManageMemory) { - TValue * temp = this->AllocateElements(sz); // may throw + auto temp = make_unique_for_overwrite(sz); // may throw itkAssertInDebugAndIgnoreInReleaseMacro(temp); itkAssertInDebugAndIgnoreInReleaseMacro(m_NumElements == 0 || (m_NumElements > 0 && m_Data != nullptr)); - keepValues(sz, m_NumElements, m_Data, temp); // possible leak if TValue copy may throw + keepValues(sz, m_NumElements, m_Data, temp.get()); // commit changes if (m_LetArrayManageMemory) { delete[] m_Data; } - m_Data = temp; + m_Data = temp.release(); m_LetArrayManageMemory = true; } m_NumElements = sz; From f080d4fa3303b8b1286656bb8756d20bc6d3cc79 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Tue, 23 Dec 2025 11:49:08 +0100 Subject: [PATCH 2/2] STYLE: FUTURE REMOVE/deprecate `VariableLengthVector::AllocateElements` Although AllocateElements is a public member function of VariableLengthVector, it was only used internally, by VariableLengthVector itself. --- Modules/Core/Common/include/itkVariableLengthVector.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Modules/Core/Common/include/itkVariableLengthVector.h b/Modules/Core/Common/include/itkVariableLengthVector.h index ccc658d28c3..817281657f8 100644 --- a/Modules/Core/Common/include/itkVariableLengthVector.h +++ b/Modules/Core/Common/include/itkVariableLengthVector.h @@ -761,12 +761,15 @@ class ITK_TEMPLATE_EXPORT VariableLengthVector void Reserve(ElementIdentifier size); +#ifndef ITK_FUTURE_LEGACY_REMOVE /** Allocate memory of certain size and return it. * \return a non-null pointer to an array of \c size elements (0 is a valid * parameter). + * \deprecated Please consider calling `std::make_unique(size)` instead. */ - [[nodiscard]] TValue * + [[deprecated("Please consider calling `std::make_unique(size)` instead.")]] [[nodiscard]] TValue * AllocateElements(ElementIdentifier size) const; +#endif [[nodiscard]] const TValue * GetDataPointer() const