In the previous code, the old m_pData is deleted before it is renewed. If an exception is thrown while
reallocating memory due to insufficient memory, m_pData is a NULL pointer and it is prone to crash the
whole application. In other words, when an exception is thrown in the assignment operator function, the
status of a CMyString instance is invalid. It breaks the requirement of exception safety: If an exception is
thrown, everything in the program must remain in a valid state.
Two approaches are available to achieve the goal of exception safety. The first one is to allocate memory with the new operator before deleting. It makes sure the old memory is deleted only after it allocates memory successfully, and the status of CMyString instances is valid if it fails to allocate memory.
A better choice is to create a temporary instance to copy the input data and then to swap it with the target. The code in Listing 2-11 is based on the copy-and-swap solution.
Listing 2-11. C++ Code for Assignment Operator (Version 2)
It allocates memory with the new operator in the constructor of CMyString. Supposing that a bad_alloc exception is thrown due to insufficient memory, the old instance has not been modified, and its status is still valid. Therefore, it is an exception-safe solution.
Source Code:
Two approaches are available to achieve the goal of exception safety. The first one is to allocate memory with the new operator before deleting. It makes sure the old memory is deleted only after it allocates memory successfully, and the status of CMyString instances is valid if it fails to allocate memory.
A better choice is to create a temporary instance to copy the input data and then to swap it with the target. The code in Listing 2-11 is based on the copy-and-swap solution.
Listing 2-11. C++ Code for Assignment Operator (Version 2)
CMyString& CMyString::operator =(const CMyString &str) {
if(this != &str) {
CMyString strTemp(str);
char* pTemp = strTemp.m_pData;
strTemp.m_pData = m_pData;
m_pData = pTemp;
}
return *this;
}
In this code, a temporary instance strTemp is constructed first, copying data from the input str. Next,
it swaps strTemp.m_pData with this->m_pData. Because strTemp is a local variable, its destructor will be
called automatically when the execution flow exits this function. The memory pointed to by
strTemp.m_pData is what was pointed to by this->m_pData before, so the memory of the old instance is
deleted when the destructor of strTemp is invoked.
It allocates memory with the new operator in the constructor of CMyString. Supposing that a bad_alloc exception is thrown due to insufficient memory, the old instance has not been modified, and its status is still valid. Therefore, it is an exception-safe solution.
Source Code:
002_AssignmentOperator.cpp
Test Cases:- Assign an instance to another
- Assign an instance to itself
- Chain multiple assignments together
- Stress tests to check whether the code contains memory leaks
No comments:
Post a Comment