So, I have created a derived class template called unorderedSet that uses a pointer member variable to hold the location of an array on the heap (using new).
I am trying to overload the arithmetic operators to find both the intersection and union of two different unorderedSet objects, but my code terminates at the end of the first overloaded function call with a warning saying "reference to stack memory associated with local variable 'unSet' returned [-Wreturn-stack-address]." I will post the relevant parts of my code below.
template <class elemType>
class unorderedSet: public unorderedArrayListType<elemType>
{
public:
void insertAt(int location, const elemType& insertItem);
void insertEnd(const elemType& insertItem);
void replaceAt(int location, const elemType& repItem);
const unorderedSet<elemType>& operator (const unorderedSet<elemType>&);
// Function to overload the binary operator to find the union of a pair/group of sets
// Postcondition: Finds the union of the sets
const unorderedSet<elemType>& operator-(const unorderedSet<elemType>&);
// Function to overload the binary operator - to find the intersection of a pair/group of sets
// Postcondition: Finds the intersection of the sets
unorderedSet(int size = 100);
unorderedSet(const unorderedSet<elemType>& otherSet);
~unorderedSet();
protected:
elemType *set;
int length;
int maxSize;
};
template <class elemType>
const unorderedSet<elemType>& unorderedSet<elemType>::operator (const unorderedSet<elemType>& otherSet)
{
unorderedSet<elemType> unSet(this->length otherSet.length); // Initializes new set to hold values of the union set
for (int i = 0; i < this->length; i )
unSet.insertEnd(this->list[i]); // Assigns all values of the activating operand to the union set using insertEnd
for (int i = 0; i < otherSet.length; i )
unSet.insertEnd(otherSet.list[i]); // Calls insertEnd() to both check for duplicate values and add unique values to the union of the sets
cout << "\n\nunSet:\n";
unSet.print(); // Checks the values of the union set
//This is the last block of code my program runs that I know of
return unSet; // Should return the union set, but dumps the core at the moment
} // end operator overload
template <class elemType>
unorderedSet<elemType>::unorderedSet(int size) : unorderedArrayListType<elemType>(size)
{
if (size <= 0)
{
cout << "The array size must be positive. Creating an array of the size 100. " << endl;
this->maxSize = 100;
}
else
this->maxSize = size;
this->length = 0;
set = new elemType[this->maxSize];
}
template <class elemType>
unorderedSet<elemType>::~unorderedSet()
{
delete [] set;
}
template <class elemType>
unorderedSet<elemType>::unorderedSet(const unorderedSet<elemType>& otherSet)
{
this->maxSize = otherSet.maxSize;
this->length = otherSet.length;
set = new elemType[this->maxSize];
for (int j = 0; j < length; j )
set[j] = otherSet.set[j];
}
The cout statements before the return values are what allow me to check that the function is doing its job up to that point, and, so far, it all works as it should.
The following code comes from my test client program.
int main()
{
int intArr1[6] = {0, 1, 2, 3, 4, 5};
unorderedSet<int> testIntSet1;
for (int i = 0; i < (sizeof(intArr1) / sizeof(intArr1[0])); i )
testIntSet1.insertEnd(intArr1[i]);
// Some more code before the function call
int intArr2[6] = {0, 1, 3, 6, 7, 9};
unorderedSet<int> testIntSet2, testIntSet3;
for (int i = 0; i < (sizeof(intArr2) / sizeof(intArr2[0])); i )
testIntSet2.insertEnd(intArr2[i]);
testIntSet3 = testIntSet1 testIntSet2;
// Some more code
}
Nothing after the last line in the client program runs, so know that is the issue. What I'm struggling with is how to fix my operator overload function so that the return value does not return a reference to a memory address that is destroyed once the function ends. I have read a lot of posts on this site where users often suggest using either malloc or calloc, but I'm not sure that is what I need to do, so I figured I would post some code and ask you guys.
CodePudding user response:
The issue is that you're returning a reference to a stack object, who's lifetime is the scope of the operator
function.
template <class elemType>
const unorderedSet<elemType>& unorderedSet<elemType>::operator (const unorderedSet<elemType>& otherSet)
Notice that you're returning a const unorderedSet<elemType>&
, a reference to the set.
All you have to do is return an object, which will be copied to the target variable (although compilers will most likely optimize this with RVO, eliminating the copy)
All this requires is changing the return type to be an object, rather than a reference:
template <class elemType>
const unorderedSet<elemType> unorderedSet<elemType>::operator (const unorderedSet<elemType>& otherSet)