diff --git a/autotest/cpp/test_ogr.cpp b/autotest/cpp/test_ogr.cpp index 9f2de42a3150..b4f96c1d7233 100644 --- a/autotest/cpp/test_ogr.cpp +++ b/autotest/cpp/test_ogr.cpp @@ -368,6 +368,60 @@ TEST_F(test_ogr, OGRCurvePolygon_copy_constructor_illegal_use) EXPECT_TRUE(poly.IsEmpty()); } +template void testMove() +{ + auto poSRS = new OGRSpatialReference(); + { + auto poOrigin = std::unique_ptr(make()); + ASSERT_TRUE(nullptr != poOrigin); + poOrigin->assignSpatialReference(poSRS); + + T valueCopy(*poOrigin); + const int refCountBefore = poSRS->GetReferenceCount(); + T fromMoved(std::move(*poOrigin)); + EXPECT_EQ(poSRS->GetReferenceCount(), refCountBefore); + + ASSERT_TRUE(CPL_TO_BOOL(fromMoved.Equals(&valueCopy))) + << valueCopy.getGeometryName() + << ": move constructor changed a value"; + EXPECT_EQ(fromMoved.getSpatialReference(), poSRS); + + T valueCopy2(valueCopy); + EXPECT_EQ(valueCopy.getSpatialReference(), poSRS); + T value3; + const int refCountBefore2 = poSRS->GetReferenceCount(); + value3 = std::move(valueCopy); + EXPECT_EQ(poSRS->GetReferenceCount(), refCountBefore2); + + ASSERT_TRUE(CPL_TO_BOOL(value3.Equals(&valueCopy2))) + << valueCopy2.getGeometryName() + << ": move assignment operator changed a value"; + EXPECT_EQ(value3.getSpatialReference(), poSRS); + } + EXPECT_EQ(poSRS->GetReferenceCount(), 1); + poSRS->Release(); +} + +TEST_F(test_ogr, geometry_move) +{ + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); + testMove(); +} + TEST_F(test_ogr, geometry_get_point) { { diff --git a/ogr/ogr_geometry.h b/ogr/ogr_geometry.h index abd66ace0e8f..5bc1134e7c25 100644 --- a/ogr/ogr_geometry.h +++ b/ogr/ogr_geometry.h @@ -407,9 +407,11 @@ class CPL_DLL OGRGeometry OGRGeometry(); OGRGeometry(const OGRGeometry &other); + OGRGeometry(OGRGeometry &&other); virtual ~OGRGeometry(); OGRGeometry &operator=(const OGRGeometry &other); + OGRGeometry &operator=(OGRGeometry &&other); /** Returns if two geometries are equal. */ bool operator==(const OGRGeometry &other) const @@ -1144,9 +1146,13 @@ class CPL_DLL OGRPoint : public OGRGeometry OGRPoint(double x, double y, double z); OGRPoint(double x, double y, double z, double m); OGRPoint(const OGRPoint &other); + /** Move constructor */ + OGRPoint(OGRPoint &&other) = default; static OGRPoint *createXYM(double x, double y, double m); OGRPoint &operator=(const OGRPoint &other); + /** Move assignment operator */ + OGRPoint &operator=(OGRPoint &&other) = default; // IWks Interface size_t WkbSize() const override; @@ -1317,6 +1323,7 @@ class CPL_DLL OGRCurve : public OGRGeometry //! @cond Doxygen_Suppress OGRCurve() = default; OGRCurve(const OGRCurve &other) = default; + OGRCurve(OGRCurve &&other) = default; virtual OGRCurveCasterToLineString GetCasterToLineString() const = 0; virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const = 0; @@ -1350,6 +1357,7 @@ class CPL_DLL OGRCurve : public OGRGeometry public: //! @cond Doxygen_Suppress OGRCurve &operator=(const OGRCurve &other); + OGRCurve &operator=(OGRCurve &&other) = default; //! @endcond /** Type of child elements. */ @@ -1532,6 +1540,8 @@ class CPL_DLL OGRSimpleCurve : public OGRCurve OGRSimpleCurve(const OGRSimpleCurve &other); + OGRSimpleCurve(OGRSimpleCurve &&other); + private: class CPL_DLL Iterator { @@ -1576,6 +1586,8 @@ class CPL_DLL OGRSimpleCurve : public OGRCurve OGRSimpleCurve &operator=(const OGRSimpleCurve &other); + OGRSimpleCurve &operator=(OGRSimpleCurve &&other); + /** Type of child elements. */ typedef OGRPoint ChildType; @@ -1776,8 +1788,10 @@ class CPL_DLL OGRLineString : public OGRSimpleCurve /** Create an empty line string. */ OGRLineString() = default; OGRLineString(const OGRLineString &other); + OGRLineString(OGRLineString &&other); OGRLineString &operator=(const OGRLineString &other); + OGRLineString &operator=(OGRLineString &&other); virtual OGRLineString *clone() const override; virtual OGRLineString * @@ -1882,9 +1896,13 @@ class CPL_DLL OGRLinearRing : public OGRLineString /** Constructor */ OGRLinearRing() = default; OGRLinearRing(const OGRLinearRing &other); + /** Move constructor*/ + OGRLinearRing(OGRLinearRing &&other) = default; explicit OGRLinearRing(const OGRLinearRing *); OGRLinearRing &operator=(const OGRLinearRing &other); + /** Move assignment operator */ + OGRLinearRing &operator=(OGRLinearRing &&other) = default; // Non standard. virtual const char *getGeometryName() const override; @@ -1965,8 +1983,12 @@ class CPL_DLL OGRCircularString : public OGRSimpleCurve OGRCircularString() = default; OGRCircularString(const OGRCircularString &other); + /** Move constructor */ + OGRCircularString(OGRCircularString &&other) = default; OGRCircularString &operator=(const OGRCircularString &other); + /** Move assignment operator */ + OGRCircularString &operator=(OGRCircularString &&other) = default; // IWks Interface. virtual OGRErr importFromWkb(const unsigned char *, size_t, OGRwkbVariant, @@ -2074,9 +2096,11 @@ class CPL_DLL OGRCurveCollection public: OGRCurveCollection() = default; OGRCurveCollection(const OGRCurveCollection &other); + OGRCurveCollection(OGRCurveCollection &&other); ~OGRCurveCollection(); OGRCurveCollection &operator=(const OGRCurveCollection &other); + OGRCurveCollection &operator=(OGRCurveCollection &&other); /** Type of child elements. */ typedef OGRCurve ChildType; @@ -2207,8 +2231,12 @@ class CPL_DLL OGRCompoundCurve : public OGRCurve OGRCompoundCurve() = default; OGRCompoundCurve(const OGRCompoundCurve &other); + /** Move constructor */ + OGRCompoundCurve(OGRCompoundCurve &&other) = default; OGRCompoundCurve &operator=(const OGRCompoundCurve &other); + /** Move assignment operator */ + OGRCompoundCurve &operator=(OGRCompoundCurve &&other) = default; /** Type of child elements. */ typedef OGRCurve ChildType; @@ -2476,8 +2504,12 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface OGRCurvePolygon() = default; OGRCurvePolygon(const OGRCurvePolygon &); + /** Move constructor */ + OGRCurvePolygon(OGRCurvePolygon &&) = default; OGRCurvePolygon &operator=(const OGRCurvePolygon &other); + /** Move assignment operator */ + OGRCurvePolygon &operator=(OGRCurvePolygon &&other) = default; /** Type of child elements. */ typedef OGRCurve ChildType; @@ -2685,8 +2717,12 @@ class CPL_DLL OGRPolygon : public OGRCurvePolygon OGRPolygon() = default; OGRPolygon(const OGRPolygon &other); + /** Move constructor */ + OGRPolygon(OGRPolygon &&other) = default; OGRPolygon &operator=(const OGRPolygon &other); + /** Move assignment operator */ + OGRPolygon &operator=(OGRPolygon &&other) = default; /** Type of child elements. */ typedef OGRLinearRing ChildType; @@ -2856,8 +2892,12 @@ class CPL_DLL OGRTriangle : public OGRPolygon OGRTriangle() = default; OGRTriangle(const OGRPoint &p, const OGRPoint &q, const OGRPoint &r); OGRTriangle(const OGRTriangle &other); + /** Move constructor */ + OGRTriangle(OGRTriangle &&other) = default; OGRTriangle(const OGRPolygon &other, OGRErr &eErr); OGRTriangle &operator=(const OGRTriangle &other); + /** Move assignment operator */ + OGRTriangle &operator=(OGRTriangle &&other) = default; virtual const char *getGeometryName() const override; virtual OGRwkbGeometryType getGeometryType() const override; @@ -2938,9 +2978,11 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry OGRGeometryCollection() = default; OGRGeometryCollection(const OGRGeometryCollection &other); + OGRGeometryCollection(OGRGeometryCollection &&other); ~OGRGeometryCollection() override; OGRGeometryCollection &operator=(const OGRGeometryCollection &other); + OGRGeometryCollection &operator=(OGRGeometryCollection &&other); /** Type of child elements. */ typedef OGRGeometry ChildType; @@ -3122,8 +3164,12 @@ class CPL_DLL OGRMultiSurface : public OGRGeometryCollection OGRMultiSurface() = default; OGRMultiSurface(const OGRMultiSurface &other); + /** Move constructor */ + OGRMultiSurface(OGRMultiSurface &&other) = default; OGRMultiSurface &operator=(const OGRMultiSurface &other); + /** Move assignment operator */ + OGRMultiSurface &operator=(OGRMultiSurface &&other) = default; /** Type of child elements. */ typedef OGRSurface ChildType; @@ -3290,8 +3336,12 @@ class CPL_DLL OGRMultiPolygon : public OGRMultiSurface OGRMultiPolygon() = default; OGRMultiPolygon(const OGRMultiPolygon &other); + /** Move constructor */ + OGRMultiPolygon(OGRMultiPolygon &&other) = default; OGRMultiPolygon &operator=(const OGRMultiPolygon &other); + /** Move assignment operator */ + OGRMultiPolygon &operator=(OGRMultiPolygon &&other) = default; /** Type of child elements. */ typedef OGRPolygon ChildType; @@ -3452,9 +3502,13 @@ class CPL_DLL OGRPolyhedralSurface : public OGRSurface /** Create an empty PolyhedralSurface */ OGRPolyhedralSurface() = default; - OGRPolyhedralSurface(const OGRPolyhedralSurface &poGeom); + OGRPolyhedralSurface(const OGRPolyhedralSurface &other); + /** Move constructor */ + OGRPolyhedralSurface(OGRPolyhedralSurface &&other) = default; OGRPolyhedralSurface &operator=(const OGRPolyhedralSurface &other); + /** Move assignment operator */ + OGRPolyhedralSurface &operator=(OGRPolyhedralSurface &&other) = default; /** Type of child elements. */ typedef OGRPolygon ChildType; @@ -3629,6 +3683,12 @@ class CPL_DLL OGRTriangulatedSurface : public OGRPolyhedralSurface OGRTriangulatedSurface() = default; OGRTriangulatedSurface(const OGRTriangulatedSurface &other); + /** Move constructor */ + OGRTriangulatedSurface(OGRTriangulatedSurface &&other) = default; + + OGRTriangulatedSurface &operator=(const OGRTriangulatedSurface &other); + /** Move assignment operator */ + OGRTriangulatedSurface &operator=(OGRTriangulatedSurface &&other) = default; /** Type of child elements. */ typedef OGRTriangle ChildType; @@ -3661,7 +3721,6 @@ class CPL_DLL OGRTriangulatedSurface : public OGRPolyhedralSurface return reinterpret_cast(oMP.end()); } - OGRTriangulatedSurface &operator=(const OGRTriangulatedSurface &other); virtual const char *getGeometryName() const override; virtual OGRwkbGeometryType getGeometryType() const override; virtual OGRTriangulatedSurface *clone() const override; @@ -3764,8 +3823,12 @@ class CPL_DLL OGRMultiPoint : public OGRGeometryCollection OGRMultiPoint() = default; OGRMultiPoint(const OGRMultiPoint &other); + /** Move constructor */ + OGRMultiPoint(OGRMultiPoint &&other) = default; OGRMultiPoint &operator=(const OGRMultiPoint &other); + /** Move assignment operator */ + OGRMultiPoint &operator=(OGRMultiPoint &&other) = default; /** Type of child elements. */ typedef OGRPoint ChildType; @@ -3922,8 +3985,12 @@ class CPL_DLL OGRMultiCurve : public OGRGeometryCollection OGRMultiCurve() = default; OGRMultiCurve(const OGRMultiCurve &other); + /** Move constructor */ + OGRMultiCurve(OGRMultiCurve &&other) = default; OGRMultiCurve &operator=(const OGRMultiCurve &other); + /** Move assignment operator */ + OGRMultiCurve &operator=(OGRMultiCurve &&other) = default; /** Type of child elements. */ typedef OGRCurve ChildType; @@ -4075,8 +4142,12 @@ class CPL_DLL OGRMultiLineString : public OGRMultiCurve OGRMultiLineString() = default; OGRMultiLineString(const OGRMultiLineString &other); + /** Move constructor */ + OGRMultiLineString(OGRMultiLineString &&other) = default; OGRMultiLineString &operator=(const OGRMultiLineString &other); + /** Move assignment operator */ + OGRMultiLineString &operator=(OGRMultiLineString &&other) = default; /** Type of child elements. */ typedef OGRLineString ChildType; diff --git a/ogr/ogrcurvecollection.cpp b/ogr/ogrcurvecollection.cpp index 83f3ae2e063a..38132dca41e7 100644 --- a/ogr/ogrcurvecollection.cpp +++ b/ogr/ogrcurvecollection.cpp @@ -59,6 +59,23 @@ OGRCurveCollection::OGRCurveCollection(const OGRCurveCollection &other) } } +/************************************************************************/ +/* OGRCurveCollection( OGRCurveCollection&& ) */ +/************************************************************************/ + +/** + * \brief Move constructor. + * + * @since GDAL 3.11 + */ + +OGRCurveCollection::OGRCurveCollection(OGRCurveCollection &&other) + : nCurveCount(other.nCurveCount), papoCurves(other.papoCurves) +{ + other.nCurveCount = 0; + other.papoCurves = nullptr; +} + /************************************************************************/ /* ~OGRCurveCollection() */ /************************************************************************/ @@ -107,6 +124,27 @@ OGRCurveCollection::operator=(const OGRCurveCollection &other) return *this; } +/************************************************************************/ +/* operator=( OGRCurveCollection&& ) */ +/************************************************************************/ + +/** + * \brief Move assignment operator. + * + * @since GDAL 3.11 + */ + +OGRCurveCollection &OGRCurveCollection::operator=(OGRCurveCollection &&other) +{ + if (this != &other) + { + empty(nullptr); + std::swap(nCurveCount, other.nCurveCount); + std::swap(papoCurves, other.papoCurves); + } + return *this; +} + /************************************************************************/ /* WkbSize() */ /************************************************************************/ diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp index e18e1b467526..e7a1cb4c5025 100644 --- a/ogr/ogrgeometry.cpp +++ b/ogr/ogrgeometry.cpp @@ -109,6 +109,22 @@ OGRGeometry::OGRGeometry(const OGRGeometry &other) const_cast(poSRS)->Reference(); } +/************************************************************************/ +/* OGRGeometry( OGRGeometry&& ) */ +/************************************************************************/ + +/** + * \brief Move constructor. + * + * @since GDAL 3.11 + */ + +OGRGeometry::OGRGeometry(OGRGeometry &&other) + : poSRS(other.poSRS), flags(other.flags) +{ + other.poSRS = nullptr; +} + /************************************************************************/ /* ~OGRGeometry() */ /************************************************************************/ @@ -144,6 +160,27 @@ OGRGeometry &OGRGeometry::operator=(const OGRGeometry &other) return *this; } +/************************************************************************/ +/* operator=( OGRGeometry&&) */ +/************************************************************************/ + +/** + * \brief Move assignment operator. + * + * @since GDAL 3.11 + */ + +OGRGeometry &OGRGeometry::operator=(OGRGeometry &&other) +{ + if (this != &other) + { + poSRS = other.poSRS; + other.poSRS = nullptr; + flags = other.flags; + } + return *this; +} + /************************************************************************/ /* dumpReadable() */ /************************************************************************/ diff --git a/ogr/ogrgeometrycollection.cpp b/ogr/ogrgeometrycollection.cpp index 915dc7f0ca86..f1beb953ad96 100644 --- a/ogr/ogrgeometrycollection.cpp +++ b/ogr/ogrgeometrycollection.cpp @@ -57,6 +57,27 @@ OGRGeometryCollection::OGRGeometryCollection(const OGRGeometryCollection &other) } } +/************************************************************************/ +/* OGRGeometryCollection( OGRGeometryCollection&& ) */ +/************************************************************************/ + +/** + * \brief Move constructor. + * + * @since GDAL 3.11 + */ + +// cppcheck-suppress-begin accessMoved +OGRGeometryCollection::OGRGeometryCollection(OGRGeometryCollection &&other) + : OGRGeometry(std::move(other)), nGeomCount(other.nGeomCount), + papoGeoms(other.papoGeoms) +{ + other.nGeomCount = 0; + other.papoGeoms = nullptr; +} + +// cppcheck-suppress-end accessMoved + /************************************************************************/ /* ~OGRGeometryCollection() */ /************************************************************************/ @@ -112,6 +133,30 @@ OGRGeometryCollection::operator=(const OGRGeometryCollection &other) return *this; } +/************************************************************************/ +/* operator=( OGRGeometryCollection&&) */ +/************************************************************************/ + +/** + * \brief Move assignment operator. + * + * @since GDAL 3.11 + */ + +OGRGeometryCollection & +OGRGeometryCollection::operator=(OGRGeometryCollection &&other) +{ + if (this != &other) + { + empty(); + + OGRGeometry::operator=(std::move(other)); + std::swap(nGeomCount, other.nGeomCount); + std::swap(papoGeoms, other.papoGeoms); + } + return *this; +} + /************************************************************************/ /* empty() */ /************************************************************************/ diff --git a/ogr/ogrlinestring.cpp b/ogr/ogrlinestring.cpp index 80445fea3b6d..929b570901e0 100644 --- a/ogr/ogrlinestring.cpp +++ b/ogr/ogrlinestring.cpp @@ -60,6 +60,31 @@ OGRSimpleCurve::OGRSimpleCurve(const OGRSimpleCurve &other) setPoints(other.nPointCount, other.paoPoints, other.padfZ, other.padfM); } +/************************************************************************/ +/* OGRSimpleCurve( OGRSimpleCurve&& ) */ +/************************************************************************/ + +/** + * \brief Move constructor. + * + * @since GDAL 3.11 + */ + +// cppcheck-suppress-begin accessMoved +OGRSimpleCurve::OGRSimpleCurve(OGRSimpleCurve &&other) + : OGRCurve(std::move(other)), nPointCount(other.nPointCount), + m_nPointCapacity(other.m_nPointCapacity), paoPoints(other.paoPoints), + padfZ(other.padfZ), padfM(other.padfM) +{ + other.nPointCount = 0; + other.m_nPointCapacity = 0; + other.paoPoints = nullptr; + other.padfZ = nullptr; + other.padfM = nullptr; +} + +// cppcheck-suppress-end accessMoved + /************************************************************************/ /* ~OGRSimpleCurve() */ /************************************************************************/ @@ -73,7 +98,7 @@ OGRSimpleCurve::~OGRSimpleCurve() } /************************************************************************/ -/* operator=( const OGRPoint& ) */ +/* operator=(const OGRSimpleCurve &other) */ /************************************************************************/ /** @@ -98,6 +123,43 @@ OGRSimpleCurve &OGRSimpleCurve::operator=(const OGRSimpleCurve &other) return *this; } +/************************************************************************/ +/* operator=(OGRSimpleCurve &&other) */ +/************************************************************************/ + +/** + * \brief Move assignment operator. + * + * @since GDAL 3.11 + */ + +OGRSimpleCurve &OGRSimpleCurve::operator=(OGRSimpleCurve &&other) +{ + if (this != &other) + { + // cppcheck-suppress-begin accessMoved + OGRCurve::operator=(std::move(other)); + + nPointCount = other.nPointCount; + m_nPointCapacity = other.m_nPointCapacity; + CPLFree(paoPoints); + paoPoints = other.paoPoints; + CPLFree(padfZ); + padfZ = other.padfZ; + CPLFree(padfM); + padfM = other.padfM; + flags = other.flags; + other.nPointCount = 0; + other.m_nPointCapacity = 0; + other.paoPoints = nullptr; + other.padfZ = nullptr; + other.padfM = nullptr; + // cppcheck-suppress-end accessMoved + } + + return *this; +} + /************************************************************************/ /* flattenTo2D() */ /************************************************************************/ @@ -2806,6 +2868,18 @@ OGRPointIterator *OGRSimpleCurve::getPointIterator() const OGRLineString::OGRLineString(const OGRLineString &) = default; +/************************************************************************/ +/* OGRLineString( OGRLineString&& ) */ +/************************************************************************/ + +/** + * \brief Move constructor. + * + * @since GDAL 3.11 + */ + +OGRLineString::OGRLineString(OGRLineString &&) = default; + /************************************************************************/ /* operator=( const OGRLineString& ) */ /************************************************************************/ @@ -2828,6 +2902,25 @@ OGRLineString &OGRLineString::operator=(const OGRLineString &other) return *this; } +/************************************************************************/ +/* operator=( OGRLineString&& ) */ +/************************************************************************/ + +/** + * \brief Move assignment operator. + * + * @since GDAL 3.11 + */ + +OGRLineString &OGRLineString::operator=(OGRLineString &&other) +{ + if (this != &other) + { + OGRSimpleCurve::operator=(std::move(other)); + } + return *this; +} + /************************************************************************/ /* getGeometryType() */ /************************************************************************/ diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh index c1d1ce89f561..f3b9932c2077 100755 --- a/scripts/cppcheck.sh +++ b/scripts/cppcheck.sh @@ -180,6 +180,12 @@ mv ${LOG_FILE}.tmp ${LOG_FILE} grep -v -e "The comparison '0 <= yystate' is always true" ${LOG_FILE} > ${LOG_FILE}.tmp mv ${LOG_FILE}.tmp ${LOG_FILE} +# False positives with cppcheck of ubuntu 20.04 +grep -v -e "ogrlinestring.cpp:.*warning,accessMoved" ${LOG_FILE} > ${LOG_FILE}.tmp +mv ${LOG_FILE}.tmp ${LOG_FILE} +grep -v -e "ogrgeometrycollection.cpp:.*warning,accessMoved" ${LOG_FILE} > ${LOG_FILE}.tmp +mv ${LOG_FILE}.tmp ${LOG_FILE} + if grep "null pointer" ${LOG_FILE} ; then echo "Null pointer check failed" ret_code=1