mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
0029258: Foundation Classes - provide move constructors for string classes
New macro OCCT_NO_RVALUE_REFERENCE is introduced to disable methods using move semantics on obsolete compilers that do not support rvalue references. TCollection_AsciiString, TCollection_ExtendedString, NCollection_UtfString - added method Swap(), move constructor, and move assignment operator. Draw command QATestArrayMove is added to test for memory corruption if NCollection_Array1<> bound to local C buffer is returned from function by value.
This commit is contained in:
@@ -155,6 +155,7 @@ public:
|
||||
// ---------- PUBLIC METHODS ------------
|
||||
|
||||
//! Empty constructor; should be used with caution.
|
||||
//! @sa methods Resize() and Move().
|
||||
NCollection_Array1()
|
||||
: myLowerBound (1),
|
||||
myUpperBound (0),
|
||||
@@ -188,25 +189,36 @@ public:
|
||||
Standard_OutOfMemory_Raise_if (!pBegin, "NCollection_Array1 : Allocation failed");
|
||||
myData = pBegin - myLowerBound;
|
||||
|
||||
*this = theOther;
|
||||
Assign (theOther);
|
||||
}
|
||||
|
||||
#ifndef OCCT_NO_RVALUE_REFERENCE
|
||||
//! Move constructor
|
||||
#if(defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
#else
|
||||
NCollection_Array1 (NCollection_Array1&& theOther)
|
||||
: myLowerBound (theOther.myLowerBound),
|
||||
myUpperBound (theOther.myUpperBound),
|
||||
myDeletable (theOther.myDeletable),
|
||||
myData (theOther.myData)
|
||||
{
|
||||
theOther.myUpperBound = theOther.myLowerBound - 1;
|
||||
theOther.myDeletable = false;
|
||||
theOther.myData = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
//! C array-based constructor
|
||||
//! C array-based constructor.
|
||||
//!
|
||||
//! Makes this array to use the buffer pointed by theBegin
|
||||
//! instead of allocating it dynamically.
|
||||
//! Argument theBegin should be a reference to the first element
|
||||
//! of the pre-allocated buffer (usually local C array buffer),
|
||||
//! with size at least theUpper - theLower + 1 items.
|
||||
//!
|
||||
//! Warning: returning array object created using this constructor
|
||||
//! from function by value will result in undefined behavior
|
||||
//! if compiler performs return value optimization (this is likely
|
||||
//! to be true for all modern compilers in release mode).
|
||||
//! The same happens if array is copied using Move() function
|
||||
//! or move constructor and target object's lifespan is longer
|
||||
//! than that of the buffer.
|
||||
NCollection_Array1 (const TheItemType& theBegin,
|
||||
const Standard_Integer theLower,
|
||||
const Standard_Integer theUpper) :
|
||||
@@ -262,7 +274,9 @@ public:
|
||||
Standard_Boolean IsAllocated (void) const
|
||||
{ return myDeletable; }
|
||||
|
||||
//! Assignment
|
||||
//! Copies data of theOther array to this.
|
||||
//! This array should be pre-allocated and have the same length as theOther;
|
||||
//! otherwise exception Standard_DimensionMismatch is thrown.
|
||||
NCollection_Array1& Assign (const NCollection_Array1& theOther)
|
||||
{
|
||||
if (&theOther == this)
|
||||
@@ -281,7 +295,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Move assignment
|
||||
//! Move assignment.
|
||||
//! This array will borrow all the data from theOther.
|
||||
//! The moved object will keep pointer to the memory buffer and
|
||||
//! range, but it will not free the buffer on destruction.
|
||||
NCollection_Array1& Move (NCollection_Array1& theOther)
|
||||
{
|
||||
if (&theOther == this)
|
||||
@@ -293,26 +310,25 @@ public:
|
||||
{
|
||||
delete[] &myData[myLowerBound];
|
||||
}
|
||||
|
||||
myLowerBound = theOther.myLowerBound;
|
||||
myUpperBound = theOther.myUpperBound;
|
||||
myDeletable = theOther.myDeletable;
|
||||
myData = theOther.myData;
|
||||
|
||||
theOther.myUpperBound = theOther.myLowerBound - 1;
|
||||
theOther.myDeletable = Standard_False;
|
||||
theOther.myData = NULL;
|
||||
theOther.myDeletable = Standard_False;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
//! Assignment operator; @sa Assign()
|
||||
NCollection_Array1& operator= (const NCollection_Array1& theOther)
|
||||
{
|
||||
return Assign (theOther);
|
||||
}
|
||||
|
||||
//! Move assignment operator.
|
||||
#if(defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
#else
|
||||
#ifndef OCCT_NO_RVALUE_REFERENCE
|
||||
//! Move assignment operator; @sa Move()
|
||||
NCollection_Array1& operator= (NCollection_Array1&& theOther)
|
||||
{
|
||||
return Move (theOther);
|
||||
@@ -424,7 +440,10 @@ public:
|
||||
|
||||
//! Destructor - releases the memory
|
||||
~NCollection_Array1 (void)
|
||||
{ if (myDeletable) delete [] &(myData[myLowerBound]); }
|
||||
{
|
||||
if (myDeletable)
|
||||
delete [] &(myData[myLowerBound]);
|
||||
}
|
||||
|
||||
protected:
|
||||
// ---------- PROTECTED FIELDS -----------
|
||||
|
@@ -80,6 +80,11 @@ public:
|
||||
//! @param theCopy string to copy.
|
||||
NCollection_UtfString (const NCollection_UtfString& theCopy);
|
||||
|
||||
#ifndef OCCT_NO_RVALUE_REFERENCE
|
||||
//! Move constructor
|
||||
NCollection_UtfString (NCollection_UtfString&& theOther);
|
||||
#endif
|
||||
|
||||
//! Copy constructor from UTF-8 string.
|
||||
//! @param theCopyUtf8 UTF-8 string to copy
|
||||
//! @param theLength optional length limit in Unicode symbols (NOT bytes!)
|
||||
@@ -196,7 +201,18 @@ public:
|
||||
public: //! @name assign operators
|
||||
|
||||
//! Copy from another string.
|
||||
const NCollection_UtfString& operator= (const NCollection_UtfString& theOther);
|
||||
const NCollection_UtfString& Assign (const NCollection_UtfString& theOther);
|
||||
|
||||
//! Exchange the data of two strings (without reallocating memory).
|
||||
void Swap (NCollection_UtfString& theOther);
|
||||
|
||||
//! Copy from another string.
|
||||
const NCollection_UtfString& operator= (const NCollection_UtfString& theOther) { return Assign (theOther); }
|
||||
|
||||
#ifndef OCCT_NO_RVALUE_REFERENCE
|
||||
//! Move assignment operator.
|
||||
NCollection_UtfString& operator= (NCollection_UtfString&& theOther) { Swap (theOther); return *this; }
|
||||
#endif
|
||||
|
||||
//! Copy from UTF-8 NULL-terminated string.
|
||||
const NCollection_UtfString& operator= (const char* theStringUtf8);
|
||||
|
@@ -90,6 +90,23 @@ NCollection_UtfString<Type>::NCollection_UtfString (const NCollection_UtfString&
|
||||
strCopy ((Standard_Byte* )myString, (const Standard_Byte* )theCopy.myString, mySize);
|
||||
}
|
||||
|
||||
#ifndef OCCT_NO_RVALUE_REFERENCE
|
||||
// =======================================================================
|
||||
// function : NCollection_UtfString
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<typename Type> inline
|
||||
NCollection_UtfString<Type>::NCollection_UtfString (NCollection_UtfString&& theOther)
|
||||
: myString(theOther.myString),
|
||||
mySize (theOther.mySize),
|
||||
myLength(theOther.myLength)
|
||||
{
|
||||
theOther.myString = NULL;
|
||||
theOther.mySize = 0;
|
||||
theOther.myLength = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// =======================================================================
|
||||
// function : NCollection_UtfString
|
||||
// purpose :
|
||||
@@ -159,11 +176,11 @@ NCollection_UtfString<Type>::~NCollection_UtfString()
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : operator=
|
||||
// function : Assign
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<typename Type> inline
|
||||
const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const NCollection_UtfString<Type>& theOther)
|
||||
const NCollection_UtfString<Type>& NCollection_UtfString<Type>::Assign (const NCollection_UtfString<Type>& theOther)
|
||||
{
|
||||
if (this == &theOther)
|
||||
{
|
||||
@@ -178,6 +195,26 @@ const NCollection_UtfString<Type>& NCollection_UtfString<Type>::operator= (const
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Swap
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
template<typename Type> inline
|
||||
void NCollection_UtfString<Type>::Swap (NCollection_UtfString<Type>& theOther)
|
||||
{
|
||||
// Note: we could use std::swap() here, but prefer to not
|
||||
// have dependency on <algorithm> header at that level
|
||||
Type* aString = myString;
|
||||
const Standard_Integer aSize = mySize;
|
||||
const Standard_Integer aLength = myLength;
|
||||
myString = theOther.myString;
|
||||
mySize = theOther.mySize;
|
||||
myLength = theOther.myLength;
|
||||
theOther.myString = aString;
|
||||
theOther.mySize = aSize;
|
||||
theOther.myLength = aLength;
|
||||
}
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
//! Auxiliary convertion tool.
|
||||
class NCollection_UtfStringTool
|
||||
|
Reference in New Issue
Block a user